Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/331.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# 通过解析获取实例的方法的单元测试<;T>;自动传真机_C#_Unit Testing_Dependency Injection_Autofac - Fatal编程技术网

C# 通过解析获取实例的方法的单元测试<;T>;自动传真机

C# 通过解析获取实例的方法的单元测试<;T>;自动传真机,c#,unit-testing,dependency-injection,autofac,C#,Unit Testing,Dependency Injection,Autofac,我在尝试为服务上的方法实现单元测试时遇到了一个问题。 该项目的架构有点麻烦,更不用说 问题在于,在要测试的方法中,它调用另一个方法来获取另一个服务的实例,下面是一个小怪物: public void SendOrderEmail(string orderCode) { Order order= GetOrderService().SerachByCode(orderCode); .... Send email with the order .... } private IOrde

我在尝试为服务上的方法实现单元测试时遇到了一个问题。 该项目的架构有点麻烦,更不用说

问题在于,在要测试的方法中,它调用另一个方法来获取另一个服务的实例,下面是一个小怪物:

public void SendOrderEmail(string orderCode)
{
    Order order= GetOrderService().SerachByCode(orderCode);
    .... Send email with the order ....
}

private IOrderService GetOrderService()
{
    return OrderService = AutofacDependencyResolver.Current.ApplicationContainer.Resolve<IOrderService>();
}
public void SendOrderEmail(字符串orderCode)
{
Order Order=GetOrderService().SerachByCode(orderCode);
..随订单发送电子邮件。。。。
}
私有IOrderService GetOrderService()
{
return OrderService=AutofacDependencyResolver.Current.ApplicationContainer.Resolve();
}
请不要问为什么一个服务调用另一个服务,或者为什么该服务没有在构造函数中注入,正如我说的,这个项目的架构在某些方面很奇怪。 我只需要知道为这样的方法实现单元测试的方法是什么


谢谢大家!

我会重构一点代码,让实现此方法的类通过构造函数注入IOrderService,保存实例,然后使用它, 通过这种方式,您可以在测试期间注入伪IOrderService(或使用Automock):)


如果您真的无法更改构造函数,那么您可以使用属性来设置IOrderService,正如其他人所说,而且您可能已经意识到,您确实希望像这样重构类,并尽可能使用构造函数注入。服务位置通常被认为是一种反模式(),它特别使像这样的单元测试变得更加困难和不那么透明

然而,如果您绝对不能重构,您仍然可以通过为您通过服务位置访问的服务提供不同的注册,使这样的方法在某种程度上可以测试

在您的情况下,如果您有:

public class EmailSender
{
    public void SendOrderEmail(string orderCode)
    {
        Order order = GetOrderService().SearchByCode(orderCode);
        //....Send email with the order ....
    }

    private IOrderService GetOrderService()
    {
        return AutofacDependencyResolver.Current.ApplicationContainer.Resolve<IOrderService>();
    }
}
使用该设置,您只需要提供您正在测试的特定方法所需的模拟,假设您可以轻松地在
autofacdependencysolver
中设置容器,以便并行运行生产和测试配置。在测试项目中使用xUnit、Moq和Autofac时,可能会出现以下情况:

public class EmailSenderTests
{
    private readonly Mock<IOrderService> _orderService;
    public EmailSenderTests()
    {
        // to set up the test fixture we'll create a mock OrderService and store a reference to the mock itself for validation later on
        _orderService = new Mock<IOrderService>();
        var mockOrder = new Order();
        _orderService.Setup(os => os.SearchByCode(It.IsAny<string>()))
            .Returns(mockOrder);
    }

    private IContainer GetTestContainer()
    {
        // here we're adding just one registration we need, setting the mocked OrderService instance to be used for IOrderService
        var builder = new ContainerBuilder();
        builder.Register(c => _orderService.Object)
            .As<IOrderService>();
        return builder.Build();
    }

    [Fact]
    public void SendEmail()
    {
        AutofacDependencyResolver.SetContainer(GetTestContainer()); // set the test container on the global singleton
        var sender = new EmailSender();
        sender.SendOrderEmail("abc");   // internally the email sender will retrieve the mock IOrderService via service location

        // make any assertions here, e.g.

        _orderService.Verify(os=>os.SearchByCode("abc"), Times.Exactly(1));
    }
}
公共类EmailSenderTests
{
私有只读模拟订单服务;
公共电子邮件发送者测试()
{
//为了设置测试夹具,我们将创建一个mock OrderService,并存储对mock本身的引用,以便稍后进行验证
_orderService=newmock();
var mockOrder=新订单();
_orderService.Setup(os=>os.SearchByCode(It.IsAny()))
.退货(订单);
}
私有IContainer GetTestContainer()
{
//在这里,我们只添加一个需要的注册,将模拟的OrderService实例设置为用于IOrderService
var builder=new ContainerBuilder();
builder.Register(c=>\u orderService.Object)
.As();
返回builder.Build();
}
[事实]
public void sendmail()
{
AutofacDependencyResolver.SetContainer(GetTestContainer());//在全局单例上设置测试容器
var sender=新的EmailSender();
sender.SendOrderEmail(“abc”);//在内部,电子邮件发件人将通过服务位置检索模拟IOrderService
//在这里做任何断言,例如。
_Verify(os=>os.SearchByCode(“abc”),Times.execute(1));
}
}

Cab是否为autofac容器提供模拟,以便返回的IOrderService本身就是模拟?您可能需要向autofac注册一个模拟服务,而不是我应该在单元测试项目中安装autofac。对吗?
public class EmailSenderTests
{
    private readonly Mock<IOrderService> _orderService;
    public EmailSenderTests()
    {
        // to set up the test fixture we'll create a mock OrderService and store a reference to the mock itself for validation later on
        _orderService = new Mock<IOrderService>();
        var mockOrder = new Order();
        _orderService.Setup(os => os.SearchByCode(It.IsAny<string>()))
            .Returns(mockOrder);
    }

    private IContainer GetTestContainer()
    {
        // here we're adding just one registration we need, setting the mocked OrderService instance to be used for IOrderService
        var builder = new ContainerBuilder();
        builder.Register(c => _orderService.Object)
            .As<IOrderService>();
        return builder.Build();
    }

    [Fact]
    public void SendEmail()
    {
        AutofacDependencyResolver.SetContainer(GetTestContainer()); // set the test container on the global singleton
        var sender = new EmailSender();
        sender.SendOrderEmail("abc");   // internally the email sender will retrieve the mock IOrderService via service location

        // make any assertions here, e.g.

        _orderService.Verify(os=>os.SearchByCode("abc"), Times.Exactly(1));
    }
}