用C#在Visual Studio写Javascript单元测试

1.在vs创建一个标准的单元测试工程

2.引用nuget包:Edge.js

我是用的是6.11.2版本

3.编写JsRunner类

using EdgeJs;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Way.UnitTest
{
    class JsRunner:IDisposable
    {
        static List<JsFileReference> ReferenceConfigs = new List<JsFileReference>();
        static List<string> GlobalJSFiles = new List<string>();
        /// <summary>
        /// 设置js文件依赖
        /// </summary>
        /// <param name="jsFile">js文件路径</param>
        /// <param name="references">所依赖的js文件路径</param>
        public static void SetJsReference(string jsFile,IEnumerable<string> references)
        {
            ReferenceConfigs.Add(new JsFileReference() {
                JsFile = jsFile,
                References = references,
            });
        }
        /// <summary>
        /// 添加全局js文件
        /// </summary>
        /// <param name="jsFile"></param>
        public static void AddGlobalJsFile(string jsFile)
        {
            GlobalJSFiles.Add(jsFile);
        }

        public JsRunner()
        {
            JsFiles.AddRange(GlobalJSFiles);
        }
        ~JsRunner()
        {
            Dispose();
        }
        List<string> JsFiles = new List<string>();
        /// <summary>
        /// 添加js文件
        /// </summary>
        /// <param name="jsPath">js文件路径</param>
        public void AddJsFile(string jsPath)
        {
            putJsFileContentToList(jsPath);
           
        }
        
        void putJsFileContentToList(string jsPath)
        {
            if (JsFiles.Contains(jsPath) )
            {
                return;
            }
            //查找该js是否引用其他js
            var arr = ReferenceConfigs.Where(m => string.Equals(m.JsFile, jsPath, StringComparison.CurrentCultureIgnoreCase));
            foreach( var item in arr )
            {
                foreach( var path in item.References )
                {
                    putJsFileContentToList(path);
                }
            }
            JsFiles.Add(jsPath);
        }

        /// <summary>
        /// 运行js代码
        /// </summary>
        /// <param name="jsCode">一段js代码。如:return data.name;</param>
        /// <param name="data">传到js里面的对象,js可以通过data.*直接使用此参数</param>
        /// <returns></returns>
        public object Run(string jsCode, object data)
        {
            StringBuilder str = new StringBuilder();
            str.AppendLine("var window = {};");

            foreach (var path in JsFiles)
            {
                str.AppendLine(readJsFile(path));
            }
            str.AppendLine(@"
                return function (data, cb) {
                    cb(null, (function(data){" + jsCode + @"})(data));
                }
            ");
            var func = Edge.Func(str.ToString());
            var task = func(data);
            task.Wait();
            return task.Result;
        }

        /// <summary>
        /// 读取js文件内容
        /// </summary>
        /// <param name="filePath"></param>
        /// <returns></returns>
        string readJsFile(string filePath)
        {
            using (System.IO.FileStream fs = System.IO.File.OpenRead(filePath))
            {
                var data = new byte[fs.Length];
                var isUtf8 = IsUTF8(fs);
                fs.Position = 0;
                fs.Read(data, 0, data.Length);
                if (isUtf8)
                { 
                    return Encoding.UTF8.GetString(data);
                }
                else
                {
                    return Encoding.GetEncoding("gb2312").GetString(data);
                }
            }
        }

        /// <summary>
        /// 判断流是否是utf-8编码
        /// </summary>
        /// <param name="stream"></param>
        /// <returns></returns>
        static bool IsUTF8(Stream stream)
        {
            bool IsUTF8 = true;

            while (stream.Position < stream.Length)
            {
                byte b = (byte)stream.ReadByte();
                if (b < 0x80) // (10000000): 值小于0x80的为ASCII字符    
                {

                }
                else if (b < (0xC0)) // (11000000): 值介于0x80与0xC0之间的为无效UTF-8字符    
                {
                    IsUTF8 = false;
                    break;
                }
                else if (b < (0xE0)) // (11100000): 此范围内为2字节UTF-8字符    
                {
                    if (stream.Position >= stream.Length - 1)
                    {
                        break;
                    }
                    byte nextByte = (byte)stream.ReadByte();
                    if ((nextByte & (0xC0)) != 0x80)
                    {
                        IsUTF8 = false;
                        break;
                    }
                }
                else if (b < (0xF0)) // (11110000): 此范围内为3字节UTF-8字符    
                {
                    if (stream.Position >= stream.Length - 2)
                    {
                        break;
                    }

                    byte nextByte1 = (byte)stream.ReadByte();
                    byte nextByte2 = (byte)stream.ReadByte();
                    if ((nextByte1 & (0xC0)) != 0x80 || (nextByte2 & (0xC0)) != 0x80)
                    {
                        IsUTF8 = false;
                        break;
                    }
                }
                else
                {
                    IsUTF8 = false;
                    break;
                }
            }

            return IsUTF8;

        }

        public void Dispose()
        {
            JsFiles.Clear();
        }
    }

    class JsFileReference
    {
        /// <summary>
        /// js文件
        /// </summary>
        public string JsFile;
        /// <summary>
        /// 所依赖的js文件
        /// </summary>
        public IEnumerable<string> References;
        
    }

}

4.编写单元测试基类

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using EdgeJs;

namespace Way.UnitTest.Javascript
{
    /// <summary>
    /// 其他js单元测试,建议继承此类
    /// </summary>
    [TestClass]
    public class JSUnitTest
    {
        protected static string Mvc_JS_Path;
        static JSUnitTest()
        {
            //组合文件夹路径
            var solutionPath = AppDomain.CurrentDomain.BaseDirectory + "\\..\\..\\..\\";
            Mvc_JS_Path= solutionPath + @"Content\js\";

            //添加全局使用的js文件
            JsRunner.AddGlobalJsFile($"{Mvc_JS_Path}\\core1.js");
            JsRunner.AddGlobalJsFile($"{Mvc_JS_Path}\\core2.js");



            //定义js文件的依赖关系
            //设置a.js依赖于b1.js  b2.js 两个文件,
            //这样,每当使用a.js文件,系统会自动引入b1.js  b2.js 两个文件
            JsRunner.SetJsReference($"{Mvc_JS_Path}\\a.js", new string[] {
                //这里写上所依赖js文件的路径
                $"{Mvc_JS_Path}\\b1.js",
                $"{Mvc_JS_Path}\\b2.js"
            });

        }

       
    }
}

5.写测试代码

using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace Way.UnitTest.Javascript
{
    [TestClass]
    public class Example:JSUnitTest
    {
        [TestMethod]
        public void TestMethod1()
        {
            using (JsRunner jsEngine = new JsRunner())
            {
                //添加一个js文件
                jsEngine.AddJsFile($"{Mvc_JS_Path}\\a.js");

                //编写js代码
                var js = @"
return data.name.StartWith('JA');
";
                //运行js代码
                var result = jsEngine.Run(js, new { name = "JACK" });
                if ((bool)result != true)
                    throw new Exception("运算结果错误");
            }
        }
    }
}

 

posted @ 2018-03-06 10:13  IWing  阅读(662)  评论(0编辑  收藏  举报