处理AutoFixture和Moq之间的标本创建不一致 [英] Handling specimen creation inconsistencies between AutoFixture and Moq

查看:68
本文介绍了处理AutoFixture和Moq之间的标本创建不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在测试约定中使用的是AutoMoqCustomization.

请考虑以下代码.在将构造函数添加到其中一个具体类之前,一切工作都很好.当我这样做时,我得到找不到无参数的构造函数".我们知道AutoFixture的构造函数没有问题,因为它为我提供了测试对象one,该对象被证明可以从IThings分配...在那里没有失败.所以一定是最小起订量.

这是有道理的,因为我假设builder是由moq生成并传递到GetCommands方法中的.因此,我认为我可以看到此时的控制已从AutoFixture传递到了最小起订量.

这说明了原因,但是我应该怎么做?有没有办法指导moq如何处理ThingOne,还是有办法指导AutoFixture忽略IThingBuilders的moq,而是执行Fixtury?

 public class TestClass
{
    public interface IThingBuilders
    {
        T1 Build<T1>() where T1 : IThings;
    }
    public interface IThings
    {
    }
    public class ThingOne : IThings
    {
        public ThingOne(string someparam)
        {
        }
    }
    public class ThingTwo : IThings
    {
    }
    public class SomeClass
    {
        public List<IThings> GetCommands(IThingBuilders builder)
        {
            var newlist = new List<IThings>();
            newlist.Add(builder.Build<ThingOne>());
            newlist.Add(builder.Build<ThingTwo>());
            return newlist;
        }
    }
    [Theory, BasicConventions]
    public void WhyCannotInstantiateProxyOfClass(ThingOne one, ThingTwo two, IThingBuilders builder, SomeClass sut)
    {
        Assert.IsAssignableFrom<IThings>(one);
        Assert.IsAssignableFrom<IThings>(two);

        var actual = sut.GetCommands(builder);

        Assert.Equal(1, actual.OfType<ThingOne>().Count());
        Assert.Equal(1, actual.OfType<ThingTwo>().Count());
    }
}
 

解决方案

由于Moq中没有可扩展性点,可以使AutoFixture挂接并提供ThingOne的值,因此您无能为力. >

但是,您可以使用Moq的SetReturnsDefault<T>方法.修改上面的测试将是这样的:

[Theory, BasicConventions]
public void WhyCannotInstantiateProxyOfClass(
    ThingOne one, ThingTwo two, IThingBuilders builder, SomeClass sut)
{
    Assert.IsAssignableFrom<IThings>(one);
    Assert.IsAssignableFrom<IThings>(two);
    Mock.Get(builder).SetReturnsDefault(one); // Add this to make the test pass

    var actual = sut.GetCommands(builder);

    Assert.Equal(1, actual.OfType<ThingOne>().Count());
    Assert.Equal(1, actual.OfType<ThingTwo>().Count());
}

这比必须编写特定的Setup/Returns对要容易一些,但并不多.您可以将该代码移到AutoFixture定制中,但是再次,由于这是Mock实例上的通用方法,因此您将需要显式调用此代码,例如ThingOne以便为该返回类型设置默认值.不是特别灵活.

I am using AutoMoqCustomization in my test conventions.

Consider the code below. Everything works great until I add a constructor to one of the concrete classes. When I do, I get "could not find a parameterless constructor". We know AutoFixture doesn't have an issue with the constructor because it delivered me the test object one which proved to be assignable from IThings... no failure there. So it must be moq.

This makes some sense because I assume builder was generated by moq and passed into the GetCommands method. So I think I can see that control has been passed from AutoFixture to moq at that point.

That takes care of the why, but what should I do about it? Is there a way to instruct moq on how to deal with the ThingOne or is there a way to instruct AutoFixture to ignore moq for IThingBuilders and instead do something Fixtury?

public class TestClass
{
    public interface IThingBuilders
    {
        T1 Build<T1>() where T1 : IThings;
    }
    public interface IThings
    {
    }
    public class ThingOne : IThings
    {
        public ThingOne(string someparam)
        {
        }
    }
    public class ThingTwo : IThings
    {
    }
    public class SomeClass
    {
        public List<IThings> GetCommands(IThingBuilders builder)
        {
            var newlist = new List<IThings>();
            newlist.Add(builder.Build<ThingOne>());
            newlist.Add(builder.Build<ThingTwo>());
            return newlist;
        }
    }
    [Theory, BasicConventions]
    public void WhyCannotInstantiateProxyOfClass(ThingOne one, ThingTwo two, IThingBuilders builder, SomeClass sut)
    {
        Assert.IsAssignableFrom<IThings>(one);
        Assert.IsAssignableFrom<IThings>(two);

        var actual = sut.GetCommands(builder);

        Assert.Equal(1, actual.OfType<ThingOne>().Count());
        Assert.Equal(1, actual.OfType<ThingTwo>().Count());
    }
}

解决方案

As there's no extensibility point in Moq that enables AutoFixture to hook in and supply a value of ThingOne, there's not a whole lot you can do.

However, you can use the SetReturnsDefault<T> method of Moq. Modifying the above test would then be like this:

[Theory, BasicConventions]
public void WhyCannotInstantiateProxyOfClass(
    ThingOne one, ThingTwo two, IThingBuilders builder, SomeClass sut)
{
    Assert.IsAssignableFrom<IThings>(one);
    Assert.IsAssignableFrom<IThings>(two);
    Mock.Get(builder).SetReturnsDefault(one); // Add this to make the test pass

    var actual = sut.GetCommands(builder);

    Assert.Equal(1, actual.OfType<ThingOne>().Count());
    Assert.Equal(1, actual.OfType<ThingTwo>().Count());
}

This is a bit easier than having to write a specific Setup/Returns pair, but not much. You could move that code to an AutoFixture Customization, but again, since this is a generic method on a a Mock instance, you'll explicitly need to call this for e.g. ThingOne in order to set the default for that return type. Not particularly flexible.

这篇关于处理AutoFixture和Moq之间的标本创建不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆