用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("运算结果错误"); } } } }