.NET测试--模拟框架NSubstitute
.NET测试--模拟框架NSubstitute
NSubstitute在GitHub的开源地址:https://github.com/nsubstitute/nsubstitute/downloads
入门
现在假设我们有一个基本的计算器界接口:
- public interface ICalculator
- {
- int Add(int a, int b);
- string Mode { get; set; }
- event EventHandler PoweringUp;
- }
使用NSubstitute创建一个替代实例。
我们可以使用stub(存根)、mock(模拟)、fake、spy、test double等。
- calculator = Substitute.For<ICalculator>();
现在我们可以使用calculator对象返回一个计算值:
- calculator.Add(1, 2).Returns(3);
- Assert.That(calculator.Add(1, 2), Is.EqualTo(3));
检测calculator对象是否执行了一个方法调用,没有执行其他的调用:
- calculator.Add(1, 2);
- calculator.Received().Add(1, 2);//是否执行了调用
- calculator.DidNotReceive().Add(5, 7);//是否没有执行调用
使用Returns方法,返回执行调用的返回值。
- calculator.Mode.Returns("DEC");
- Assert.That(calculator.Mode, Is.EqualTo("DEC"));
- calculator.Mode = "HEX";
- Assert.That(calculator.Mode, Is.EqualTo("HEX"));
NSubstitute 支持设置输入参数匹配:
- calculator.Add(10, -5);
- calculator.Received().Add(10, Arg.Any<int>());//任何int参数
- calculator.Received().Add(10, Arg.Is<int>(x => x < 0));//第二个参数小于零
使用参数匹配以及讲函数传递给Returns方法:
- calculator
- .Add(Arg.Any<int>(), Arg.Any<int>())
- .Returns(x => (int)x[0] + (int)x[1]);
- Assert.That(calculator.Add(5, 10), Is.EqualTo(15));
Returns方法返回多参数序列:
- calculator.Mode.Returns("HEX", "DEC", "BIN");
- Assert.That(calculator.Mode, Is.EqualTo("HEX"));
- Assert.That(calculator.Mode, Is.EqualTo("DEC"));
- Assert.That(calculator.Mode, Is.EqualTo("BIN"));
引发事件:
- bool eventWasRaised = false;
- calculator.PoweringUp += (sender, args) => eventWasRaised = true;
- calculator.PoweringUp += Raise.Event();
- Assert.That(eventWasRaised);
创建substitute
创建一个具有构造函数参数的类的替代:
- var someClass = Substitute.For<SomeClassWithCtorArgs>(5, "hello world");
多接口
- var command = Substitute.For<ICommand, IDisposable>();
- var runner = new CommandRunner(command);
- runner.RunCommand();
- command.Received().Execute();
- ((IDisposable)command).Received().Dispose();
可以设置多接口,但是类只能有一个:
- var substitute = Substitute.For(
- new[] { typeof(ICommand), typeof(ISomeInterface), typeof(SomeClassWithCtorArgs) },
- new object[] { 5, "hello world" }
- );
- Assert.IsInstanceOf<ICommand>(substitute);
- Assert.IsInstanceOf<ISomeInterface>(substitute);
- Assert.IsInstanceOf<SomeClassWithCtorArgs>(substitute);
代理
- var func = Substitute.For<Func<string>>();
- func().Returns("hello");
- Assert.AreEqual("hello", func());
设置返回值
- public interface ICalculator {
- int Add(int a, int b);
- string Mode { get; set; }
- }
方法
- var calculator = Substitute.For<ICalculator>();
- calculator.Add(1, 2).Returns(3);
调用的参数必须一样,返回值才会固定
- //Make a call return 3:
- calculator.Add(1, 2).Returns(3);
- Assert.AreEqual(calculator.Add(1, 2), 3);
- Assert.AreEqual(calculator.Add(1, 2), 3);
- //Call with different arguments does not return 3
- Assert.AreNotEqual(calculator.Add(3, 6), 3);
属性
- calculator.Mode.Returns("DEC");
- Assert.AreEqual(calculator.Mode, "DEC");
- calculator.Mode = "HEX";
- Assert.AreEqual(calculator.Mode, "HEX");
返回值指定输入具体参数
- //Return when first arg is anything and second arg is 5:
- //返回当第一个参数是任意int,第二个参数是5
- calculator.Add(Arg.Any<int>(), 5).Returns(10);
- Assert.AreEqual(10, calculator.Add(123, 5));
- Assert.AreEqual(10, calculator.Add(-9, 5));
- Assert.AreNotEqual(10, calculator.Add(-9, -9));
- //Return when first arg is 1 and second arg less than 0:
- //返回当第一个参数是1,第二个参数小于零
- calculator.Add(1, Arg.Is<int>(x => x < 0)).Returns(345);
- Assert.AreEqual(345, calculator.Add(1, -2));
- Assert.AreNotEqual(345, calculator.Add(1, 2));
- //Return when both args equal to 0:
- //返回当两个参数都等于0
- calculator.Add(Arg.Is(0), Arg.Is(0)).Returns(99);
- Assert.AreEqual(99, calculator.Add(0, 0));
返回值指定输入任意参数
- calculator.Add(1, 2).ReturnsForAnyArgs(100);
- Assert.AreEqual(calculator.Add(1, 2), 100);
- Assert.AreEqual(calculator.Add(-7, 15), 100);
从一个方法获取返回值
- calculator
- .Add(Arg.Any<int>(), Arg.Any<int>())
- .Returns(x => (int)x[0] + (int)x[1]);//从一个方法获取返回值
- Assert.That(calculator.Add(1, 1), Is.EqualTo(2));
- Assert.That(calculator.Add(20, 30), Is.EqualTo(50));
- Assert.That(calculator.Add(-73, 9348), Is.EqualTo(9275));
调用信息
Arg<T>()
ArgAt<T>(int position)
- public interface IFoo {
- string Bar(int a, string b);
- }
- var foo = Substitute.For<IFoo>();
- foo.Bar(0, "").ReturnsForAnyArgs(x => "Hello " + x.Arg<string>());
- Assert.That(foo.Bar(1, "World"), Is.EqualTo("Hello World"));
回调
- var counter = 0;
- calculator
- .Add(0, 0)
- .ReturnsForAnyArgs(x => {
- counter++;
- return 0;
- });
- calculator.Add(7,3);
- calculator.Add(2,2);
- calculator.Add(11,-3);
- Assert.AreEqual(counter, 3);
- var counter = 0;
- calculator
- .Add(0, 0)
- .ReturnsForAnyArgs(x => 0)
- .AndDoes(x => counter++);//?
- calculator.Add(7,3);
- calculator.Add(2,2);
- Assert.AreEqual(counter, 2);
多返回值
- calculator.Mode.Returns("DEC", "HEX", "BIN");
- Assert.AreEqual("DEC", calculator.Mode);
- Assert.AreEqual("HEX", calculator.Mode);
- Assert.AreEqual("BIN", calculator.Mode);
多返回值回调
- calculator.Mode.Returns(x => "DEC", x => "HEX", x => { throw new Exception(); });
- Assert.AreEqual("DEC", calculator.Mode);
- Assert.AreEqual("HEX", calculator.Mode);
- Assert.Throws<Exception>(() => { var result = calculator.Mode; });
替换返回值
- calculator.Mode.Returns("DEC,HEX,OCT");
- calculator.Mode.Returns(x => "???");
- calculator.Mode.Returns("HEX");
- calculator.Mode.Returns("BIN");
- Assert.AreEqual(calculator.Mode, "BIN");
检查调用,是否执行,返回
- public interface ICommand {
- void Execute();
- event EventHandler Executed;
- }
- public class SomethingThatNeedsACommand {
- ICommand command;
- public SomethingThatNeedsACommand(ICommand command) {
- this.command = command;
- }
- public void DoSomething() { command.Execute(); }
- public void DontDoAnything() { }
- }
- [Test]
- public void Should_execute_command() {
- //Arrange
- var command = Substitute.For<ICommand>();
- var something = new SomethingThatNeedsACommand(command);
- //Act
- something.DoSomething();
- //Assert 检查是否执行了这个方法
- command.Received().Execute();
- }
检查一个调用是否未执行(未返回)
- var command = Substitute.For<ICommand>();
- var something = new SomethingThatNeedsACommand(command);
- //Act
- something.DontDoAnything();
- //Assert
- command.DidNotReceive().Execute();
检查一个调用,返回执行次数
- public class CommandRepeater {
- ICommand command;
- int numberOfTimesToCall;
- public CommandRepeater(ICommand command, int numberOfTimesToCall) {
- this.command = command;
- this.numberOfTimesToCall = numberOfTimesToCall;
- }
- public void Execute() {
- for (var i=0; i<numberOfTimesToCall; i++) command.Execute();
- }
- }
- [Test]
- public void Should_execute_command_the_number_of_times_specified() {
- var command = Substitute.For<ICommand>();
- var repeater = new CommandRepeater(command, 3);
- //Act
- repeater.Execute();
- //Assert
- command.Received(3).Execute(); // << This will fail if 2 or 4 calls were received
- }
带特殊参数的返回
- calculator.Add(1, 2);
- calculator.Add(-100, 100);
- //Check received with second arg of 2 and any first arg:
- calculator.Received().Add(Arg.Any<int>(), 2);
- //Check received with first arg less than 0, and second arg of 100:
- calculator.Received().Add(Arg.Is<int>(x => x < 0), 100);
- //Check did not receive a call where second arg is >= 500 and any first arg:
- calculator
- .DidNotReceive()
- .Add(Arg.Any<int>(), Arg.Is<int>(x => x >= 500));
忽略参数
- calculator.Add(1, 3);
- calculator.ReceivedWithAnyArgs().Add(1,1);
- calculator.DidNotReceiveWithAnyArgs().Subtract(0,0);
检查属性
- var mode = calculator.Mode;
- calculator.Mode = "TEST";
- //Check received call to property getter
- //We need to assign the result to a variable to keep
- //the compiler happy.
- var temp = calculator.Received().Mode;
- //Check received call to property setter with arg of "TEST"
- calculator.Received().Mode = "TEST";
检查索引
- var dictionary = Substitute.For<IDictionary<string, int>>();
- dictionary["test"] = 1;
- dictionary.Received()["test"] = 1;
- dictionary.Received()["test"] = Arg.Is<int>(x => x < 5);
检查订阅事件
- public class CommandWatcher {
- ICommand command;
- public CommandWatcher(ICommand command) {
- command.Executed += OnExecuted;
- }
- public bool DidStuff { get; private set; }
- public void OnExecuted(object o, EventArgs e) { DidStuff = true; }
- }
- [Test]
- public void ShouldDoStuffWhenCommandExecutes() {
- var command = Substitute.For<ICommand>();
- var watcher = new CommandWatcher(command);
- command.Executed += Raise.Event();
- Assert.That(watcher.DidStuff);
- }
- [Test]
- public void MakeSureWatcherSubscribesToCommandExecuted() {
- var command = Substitute.For<ICommand>();
- var watcher = new CommandWatcher(command);
- // Not recommended. Favour testing behaviour over implementation specifics.
- // Can check subscription:
- command.Received().Executed += watcher.OnExecuted;
- // Or, if the handler is not accessible:
- command.Received().Executed += Arg.Any<EventHandler>();
- }
清除调用
- public interface ICommand {
- void Execute();
- }
- public class OnceOffCommandRunner {
- ICommand command;
- public OnceOffCommandRunner(ICommand command) {
- this.command = command;
- }
- public void Run() {
- if (command == null) return;
- command.Execute();
- command = null;
- }
- }
- var command = Substitute.For<ICommand>();
- var runner = new OnceOffCommandRunner(command);
- //First run
- runner.Run();
- command.Received().Execute();
- //Forget previous calls to command
- //清楚前面的调用
- command.ClearReceivedCalls();
- //Second run
- runner.Run();
- command.DidNotReceive().Execute();
参数匹配
忽略参数
- calculator.Add(Arg.Any<int>(), 5).Returns(7);
- Assert.AreEqual(7, calculator.Add(42, 5));
- Assert.AreEqual(7, calculator.Add(123, 5));
- Assert.AreNotEqual(7, calculator.Add(1, 7));
- formatter.Format(new object());
- formatter.Format("some string");
- formatter.Received().Format(Arg.Any<object>());
- formatter.Received().Format(Arg.Any<string>());
- formatter.DidNotReceive().Format(Arg.Any<int>());
匹配一个参数
- calculator.Add(1, -10);
- //Received call with first arg 1 and second arg less than 0:
- calculator.Received().Add(1, Arg.Is<int>(x => x < 0));
- //Received call with first arg 1 and second arg of -2, -5, or -10:
- calculator
- .Received()
- .Add(1, Arg.Is<int>(x => new[] {-2,-5,-10}.Contains(x)));
- //Did not receive call with first arg greater than 10:
- calculator.DidNotReceive().Add(Arg.Is<int>(x => x > 10), -10);
- formatter.Format(Arg.Is<string>(x => x.Length <= 10)).Returns("matched");
- Assert.AreEqual("matched", formatter.Format("short"));
- Assert.AreNotEqual("matched", formatter.Format("not matched, too long"));
- // Will not match because trying to access .Length on null will throw an exception when testing
- // our condition. NSubstitute will assume it does not match and swallow the exception.
- Assert.AreNotEqual("matched", formatter.Format(null));
匹配特殊参数
- calculator.Add(0, 42);
- //This won't work; NSubstitute isn't sure which arg the matcher applies to:
- //calculator.Received().Add(0, Arg.Any<int>());
- calculator.Received().Add(Arg.Is(0), Arg.Any<int>());
使用参数匹配
- /* ARRANGE */
- var widgetFactory = Substitute.For<IWidgetFactory>();
- var subject = new Sprocket(widgetFactory);
- // OK: Use arg matcher for a return value:
- widgetFactory.Make(Arg.Is<int>(x => x > 10)).Returns(TestWidget);
- /* ACT */
- // NOT OK: arg matcher used with a real call:
- // subject.StartWithWidget(Arg.Any<int>());
- // Use a real argument instead:
- subject.StartWithWidget(4);
- /* ASSERT */
- // OK: Use arg matcher to check a call was received:
- widgetFactory.Received().Make(Arg.Is<int>(x => x > 0));
回调,空调用
- var counter = 0;
- calculator
- .Add(0,0)
- .ReturnsForAnyArgs(x => 0)
- .AndDoes(x => counter++);
- calculator.Add(7,3);
- calculator.Add(2,2);
- calculator.Add(11,-3);
- Assert.AreEqual(counter, 3);
when...do...
- public interface IFoo {
- void SayHello(string to);
- }
- [Test]
- public void SayHello() {
- var counter = 0;
- var foo = Substitute.For<IFoo>();
- foo.When(x => x.SayHello("World"))
- .Do(x => counter++);
- foo.SayHello("World");
- foo.SayHello("World");
- Assert.AreEqual(2, counter);
- }
复杂调用
- var sub = Substitute.For<ISomething>();
- var calls = new List<string>();
- var counter = 0;
- sub
- .When(x => x.Something())
- .Do(
- Callback.First(x => calls.Add("1"))
- .Then(x => calls.Add("2"))
- .Then(x => calls.Add("3"))
- .ThenKeepDoing(x => calls.Add("+"))
- .AndAlways(x => counter++)
- );
- for (int i = 0; i < 5; i++)
- {
- sub.Something();
- }
- Assert.That(String.Concat(calls), Is.EqualTo("123++"));
- Assert.That(counter, Is.EqualTo(5));
抛出异常
- //For non-voids:
- calculator.Add(-1, -1).Returns(x => { throw new Exception(); });
- //For voids and non-voids:
- calculator
- .When(x => x.Add(-2, -2))
- .Do(x => { throw new Exception(); });
- //Both calls will now throw.
- Assert.Throws<Exception>(() => calculator.Add(-1, -1));
- Assert.Throws<Exception>(() => calculator.Add(-2, -2));
事件
- public interface IEngine {
- event EventHandler Idling;
- event EventHandler<LowFuelWarningEventArgs> LowFuelWarning;
- event Action<int> RevvedAt;
- }
- public class LowFuelWarningEventArgs : EventArgs {
- public int PercentLeft { get; private set; }
- public LowFuelWarningEventArgs(int percentLeft) {
- PercentLeft = percentLeft;
- }
- }
- var wasCalled = false;
- //设置事件
- engine.Idling += (sender, args) => wasCalled = true;
- //执行事件
- //Tell the substitute to raise the event with a sender and EventArgs:
- engine.Idling += Raise.EventWith(new object(), new EventArgs());
- Assert.True(wasCalled);
事件参数
- engine.LowFuelWarning += (sender, args) => numberOfEvents++;
- //Raise.EventWith<TEventArgs>(...)
- //Raise event with specific args, any sender:
- engine.LowFuelWarning += Raise.EventWith(new LowFuelWarningEventArgs(10));
- //Raise event with specific args and sender:
- engine.LowFuelWarning += Raise.EventWith(new object(), new LowFuelWarningEventArgs(10));
- Assert.AreEqual(2, numberOfEvents);
代理事件
- var sub = Substitute.For<INotifyPropertyChanged>();
- bool wasCalled = false;
- sub.PropertyChanged += (sender, args) => wasCalled = true;
- sub.PropertyChanged += Raise.Event<PropertyChangedEventHandler>(this, new PropertyChangedEventArgs("test"));
- Assert.That(wasCalled);
action事件
- int revvedAt = 0;;
- engine.RevvedAt += rpm => revvedAt = rpm;
- engine.RevvedAt += Raise.Event<Action<int>>(123);
- Assert.AreEqual(123, revvedAt);
自动递归模拟
递归模拟
- public interface INumberParser {
- IEnumerable<int> Parse(string expression);
- }
- public interface INumberParserFactory {
- INumberParser Create(char delimiter);
- }
- var factory = Substitute.For<INumberParserFactory>();
- var parser = Substitute.For<INumberParser>();
- factory.Create(',').Returns(parser);
- parser.Parse("an expression").Returns(new[] {1,2,3})
- Assert.AreEqual(
- factory.Create(',').Parse("an expression"),
- new[] {1,2,3});
- //or
- var factory = Substitute.For<INumberParserFactory>();
- factory.Create(',').Parse("an expression").Returns(new[] {1,2,3});
- Assert.AreEqual(
- factory.Create(',').Parse("an expression"),
- new[] {1,2,3});
- var firstCall = factory.Create(',');
- var secondCall = factory.Create(',');
- var thirdCallWithDiffArg = factory.Create('x');
- Assert.AreSame(firstCall, secondCall);
- Assert.AreNotSame(firstCall, thirdCallWithDiffArg);
Substitute chains(链)
- public interface IContext {
- IRequest CurrentRequest { get; }
- }
- public interface IRequest {
- IIdentity Identity { get; }
- IIdentity NewIdentity(string name);
- }
- public interface IIdentity {
- string Name { get; }
- string[] Roles();
- }
- var context = Substitute.For<IContext>();
- context.CurrentRequest.Identity.Name.Returns("My pet fish Eric");
- Assert.AreEqual(
- "My pet fish Eric",
- context.CurrentRequest.Identity.Name);
自动值
- var identity = Substitute.For<IIdentity>();
- Assert.AreEqual(String.Empty, identity.Name);
- Assert.AreEqual(0, identity.Roles().Length);
设置out或者ref参数
- public interface ILookup {
- bool TryLookup(string key, out string value);
- }
- //Arrange
- var value = "";
- var lookup = Substitute.For<ILookup>();
- lookup
- .TryLookup("hello", out value)
- .Returns(x => {
- x[1] = "world!";
- return true;
- });
- //Act
- var result = lookup.TryLookup("hello", out value);
- //Assert
- Assert.True(result);
- Assert.AreEqual(value, "world!");
行为和参数匹配
执行回调
- public interface IOrderProcessor {
- void ProcessOrder(int orderId, Action<bool> orderProcessed);
- }
- public class OrderPlacedCommand {
- IOrderProcessor orderProcessor;
- IEvents events;
- public OrderPlacedCommand(IOrderProcessor orderProcessor, IEvents events) {
- this.orderProcessor = orderProcessor;
- this.events = events;
- }
- public void Execute(ICart cart) {
- orderProcessor.ProcessOrder(
- cart.OrderId,
- wasOk => { if (wasOk) events.RaiseOrderProcessed(cart.OrderId); }
- );
- }
- }
- [Test]
- public void Placing_order_should_raise_order_processed_when_processing_is_successful() {
- //Arrange
- var cart = Substitute.For<ICart>();
- var events = Substitute.For<IEvents>();
- var processor = Substitute.For<IOrderProcessor>();
- cart.OrderId = 3;
- //Arrange for processor to invoke the callback arg with `true` whenever processing order id 3
- processor.ProcessOrder(3, Arg.Invoke(true));
- //Act
- var command = new OrderPlacedCommand(processor, events);
- command.Execute(cart);
- //Assert
- events.Received().RaiseOrderProcessed(3);
- }
用参数执行操作
- var argumentUsed = 0;
- calculator.Multiply(Arg.Any<int>(), Arg.Do<int>(x => argumentUsed = x));
- calculator.Multiply(123, 42);
- Assert.AreEqual(42, argumentUsed);
- var firstArgsBeingMultiplied = new List<int>();
- calculator.Multiply(Arg.Do<int>(x => firstArgsBeingMultiplied.Add(x)), 10);
- calculator.Multiply(2, 10);
- calculator.Multiply(5, 10);
- calculator.Multiply(7, 4567); //Will not match our Arg.Do as second arg is not 10
- Assert.AreEqual(firstArgsBeingMultiplied, new[] { 2, 5 });
参数规范
- var numberOfCallsWhereFirstArgIsLessThan0 = 0;
- //Specify a call where the first arg is less than 0, and the second is any int.
- //When this specification is met we'll increment a counter in the Arg.Do action for
- //the second argument that was used for the call, and we'll also make it return 123.
- calculator
- .Multiply(
- Arg.Is<int>(x => x < 0),
- Arg.Do<int>(x => numberOfCallsWhereFirstArgIsLessThan0++)
- ).Returns(123);
- var results = new[] {
- calculator.Multiply(-4, 3),
- calculator.Multiply(-27, 88),
- calculator.Multiply(-7, 8),
- calculator.Multiply(123, 2) //First arg greater than 0, so spec won't be met.
- };
- Assert.AreEqual(3, numberOfCallsWhereFirstArgIsLessThan0); //3 of 4 calls have first arg < 0
- Assert.AreEqual(results, new[] {123, 123, 123, 0}); //Last call returns 0, not 123
检查调用命令
- [Test]
- public void TestCommandRunWhileConnectionIsOpen() {
- var connection = Substitute.For<IConnection>();
- var command = Substitute.For<ICommand>();
- var subject = new Controller(connection, command);
- subject.DoStuff();
- Received.InOrder(() => {
- connection.Open();
- command.Run(connection);
- connection.Close();
- });
- }
- [Test]
- public void SubscribeToEventBeforeOpeningConnection() {
- var connection = Substitute.For<IConnection>();
- connection.SomethingHappened += () => { /* some event handler */ };
- connection.Open();
- Received.InOrder(() => {
- connection.SomethingHappened += Arg.Any<Action>();
- connection.Open();
- });
- }
.NET测试--模拟框架NSubstitute的更多相关文章
- DotNet 资源大全中文版
https://blog.csdn.net/fhzh520/article/details/52637545 目录 算法与数据结构(Algorithms and Data structures) 应用 ...
- 单元测试模拟框架:Nsubstitute
Nsubstitute是一个开源的框架,源码是C#实现的.你可以在这里获得它的源码:https://github.com/nsubstitute/NSubstitute NSubstitut ...
- .NET Core系列 :4 测试
2016.6.27 微软已经正式发布了.NET Core 1.0 RTM,但是工具链还是预览版,同样的大量的开源测试库也都是至少发布了Alpha测试版支持.NET Core, 这篇文章 The Sta ...
- mock测试框架Mockito
无论是敏捷开发.持续交付,还是测试驱动开发(TDD)都把单元测试作为实现的基石.随着这些先进的编程开发模式日益深入人心,单元测试如今显得越来越重要了.在敏捷开发.持续交付中要求单元测试一定要快(不能访 ...
- .net单元测试——常用测试方式(异常模拟、返回值测试、参数测试、数据库访问代码测试)
最近在看.net单元测试艺术,我也喜欢单元测试,今天介绍一下如何测试异常.如何测试返回值.如何测试模拟对象的参数传递.如何测试数据库访问代码.单元测试框架使用的是NUnit,模拟框架使用的是:Rhin ...
- Android测试:Building Local Unit Tests
原文:https://developer.android.com/training/testing/unit-testing/local-unit-tests.html 如果你的单元测试没有依赖或者只 ...
- Android单元测试之三:使用模拟框架模拟依赖
Android单元测试之三:使用模拟框架模拟依赖 基本描述 如果是一些工具类方法的测试,如计算两数之和的方法,本地 JVM 虚拟机就能提供足够的运行环境,但如果要测试的单元依赖了 Android 框架 ...
- Android单元测试之二:本地测试
Android单元测试之二:本地测试 本地测试 本地测试( Local tests):只在本地机器 JVM 上运行,以最小化执行时间,这种单元测试不依赖于 Android 框架,或者即使有依赖,也很方 ...
- .NET 单元测试的利剑——模拟框架Moq(简述篇)
.NET 单元测试的利剑--模拟框架Moq 前言 这篇文章是翻译文,因为通过自己参与的项目,越发觉得单元测试的重要性,特别是当跟业务数据打交道的时候的,Moq就如雪中送炭,所以想学习这个框架,就从这篇 ...
随机推荐
- 牛客挑战赛33 C 艾伦的立体机动装置(几何)
思路: 我们需要枚举展开多少条边 然后把上底面的点放到和下底面一个平面 然后算两点之间的距离 注意判断直线与线段是否有交点 #include <bits/stdc++.h> using n ...
- SPOJ1812 LCS2 - Longest Common Substring II【SAM LCS】
LCS2 - Longest Common Substring II 多个字符串找最长公共子串 以其中一个串建\(SAM\),然后用其他串一个个去匹配,每次的匹配方式和两个串找\(LCS\)一样,就是 ...
- 关于KMP算法的理解
上次因为haipz组织的比赛中有道题必须用到KMP算法,因此赛后便了解了下它,在仔细拜读了孤~影神牛的文章之后有种茅塞顿开的感觉,再次ORZ. 附上链接http://www.cnblogs.com/y ...
- Codeforces Round #630 (Div. 2)
题目链接:https://codeforces.com/contest/1332 A. Exercising Walk 可走的最远距离:左:x-x1,右:x2-x,下:y-y1,上:y2-y 如果可以 ...
- 【uva 10048】Audiophobia(图论--Floyd算法)
题意:有一个N点M边的无向带权图,边权表示路径上的噪声值.有Q个询问,输出 x,y 两点间的最大噪声值最小的路径的该值.(N≤100,M≤1000,Q≤10000) 解法:N值小,且问多对点之间的路径 ...
- Codeforces Round #582 (Div. 3) A. Chips Moving
传送门 题解: 给你n个数的坐标,你需要把他们移动到一个位置,有两种移动方式 1.向左或者右移动2 2.向左或者右移动1,但是耗费1 求最小耗费 题解: 很简单就可以想到,看一下偶数坐标多还是奇数坐标 ...
- .net core mvc 获取Web根目录和内容根目录的物理路径
从ASP.NET Core RC2开始,可以通过注入 IHostingEnvironment 服务对象来取得Web根目录和内容根目录的物理路径,如下所示: using Microsoft.AspNet ...
- Linux网络文件下载
wget 以网络下载 maven 包为例 wget -c http://mirrors.shu.edu.cn/apache/maven/maven-3/3.5.4/binaries/apache-ma ...
- Kubernets二进制安装(2)之Bind9安装
1.修改主机名 hostnamectl set-hostname mfyxw10 hostnamectl set-hostname mfyxw20 hostnamectl set-hostname m ...
- 多线程之ThreadLocal类
深入研究java.lang.ThreadLocal类 0.前言 ThreadLocal(线程变量副本)Synchronized实现内存共享,ThreadLocal为每个线程维护一个本地变量.采用空间换 ...