Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/287.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# void异步方法的断言_C#_Testing - Fatal编程技术网

C# void异步方法的断言

C# void异步方法的断言,c#,testing,C#,Testing,我有一个类似的班级: public class MyClass { public Task MyMethod() { //do something } } 如前所述,“MyMethod”是异步的,为了简单起见,我们可以说这就是它的实现: public Task MyMethod() { return Task.Run(() => { var success = _someSer

我有一个类似的班级:

public class MyClass
{
    public Task MyMethod()
    {
        //do something
    }
}
如前所述,“MyMethod”是异步的,为了简单起见,我们可以说这就是它的实现:

    public Task MyMethod()
    {
        return Task.Run(() =>
        {
            var success = _someService.DoSomething();
            if (!success) throw new Exception("unsuccsesfull");
        });

    }
显然,当MyMethod等待回调将运行时,这意味着在运行的线程中没有抛出异常,这意味着“MyMethod”调用成功

我想测试一下这个方法。测试方法如下所示:

[Test]
public async void TestMyMethod_TestInitialState_TestExpectedResult()
{
    // test initialization..
    //...
    //..
    var myClass = new MyClass();
    await myClass.MyMethod();

    Assert.That(????)
}
我的问题-正确的断言是什么

我有一个可能的解决方案-向“MyClass”添加一个逻辑成员,并根据方法结果更新此成员:

public class MyClass
{
    public bool SomeMember { get; private set; }

    public Task MyMethod()
    {
        Task.Run(() =>
        {               
            SomeMember = _someService.DoSomething();
            if (!SomeMember ) throw new Exception("unsuccsesfull");
        });

    }
}
这样,我可以像这样断言测试:

    [Test]
    public async void TestMyMethod_TestInitialState_SomeMemberShouldBeTrue()
    {
        // test initialization..
        //...
        //..
        var myClass = new MyClass();
        await myClass.MyMethod();

        Assert.True(SomeMember)
    }
}
但是,我不喜欢这个解决方案,因为我在“MyClass”中添加一个属性只是为了能够断言一个测试,在我的商业世界中我并不真正需要这个属性。此外,添加到类中的每个属性都表示该类的某些状态,并添加了一个comlexity级别

建议

伙计。

你想要所谓的“模拟”或“存根”。其思想是重构代码,使其依赖于接口,然后在测试时模拟接口

有各种框架/工具可以帮助模拟(Moq、Microsoft Fakes、TypeMock Isolator、JustMock等),还有许多框架可以帮助解决与依赖注入密切相关的问题(Unity、Castle Windsor、StructureMap、Autofac等)

但你可以自己动手。首先,重构
MyClass
,使其依赖于
ISomeService

public interface ISomeService
{
  bool DoSomething();
}

public class MyClass
{
  private readonly ISomeService _someService;

  public MyClass(ISomeService someService)
  {
    _someService = someService;
  }

  public Task MyMethod()
  {
    return Task.Run(() =>
    {
      var success = _someService.DoSomething();
      if (!success) throw new Exception("unsuccsesfull");
    });
  }
}
然后在单元测试中:

private class TestService : ISomeService
{
  public bool DoSomethingReturnValue { get; set; }

  public bool DoSomething() { return DoSomethingReturnValue; }
}

[Test]
public async Task TestMyMethod_TestInitialState_TestExpectedResult()
{
  var myClass = new MyClass(new TestService { DoSomethingReturnValue = true });
  await myClass.MyMethod();
}

[Test]
public async Task TestMyMethod_TestInitialState_TestFailure()
{
  var myClass = new MyClass(new TestService { DoSomethingReturnValue = false });
  Assert.Throws(() => myClass.MyMethod()); // (I'm unsure of the exact NUnit syntax)
}

很可能异步操作会有一些效果,否则执行它就没有意义了。它在做什么,你能测试它发生了吗?在我的例子中,它向另一台计算机发送一个文件。这是通过交换通信消息和从另一台机器请求文件的TFTP服务器发送数据来完成的。我将通过从该机器收到的一条通信消息来了解该过程是否成功,该消息指示文件处于其会话中。我无法控制此通知消息何时到达,因此我正在使用异步接口。那么,在您的测试情况下,它会做什么?在这种情况下,可能它实际上并没有做TFTP…虽然我没有问过关于嘲笑的问题,但我认为你的回答符合我的要求。。谢谢