从C#中的模拟对象中删除方法属性

问题描述:

我正在测试类的方法。但是,其中一些具有非相关内容的属性,这使得测试失败。从C#中的模拟对象中删除方法属性

例如,我有这个类(在VB.net但可能是C#以及)

<AttributeOne()> 
<AttributeTwo(Arg1, Arg2)> 
Public Overridable Function SomeMethod() As Object 
    ' Stuff 
End Function 

当我打电话SomeMethod从我的嘲笑对象,它将提出一些例外,因为属性尝试做一些东西在单元测试环境中是不可能的。

[TestFixture] 
public class SomeClassUnitTests 
{ 
    [Test] 
    public void TestSomeMethod() 
    { 
     var someClassMock = new Mock<SomeClass>() { CallBase = true }; 

     //Exception is thrown 
     var result = someClassMock.Object.SomeMethod(); 
    } 
} 

测试写在C#。我正在使用MoqNunit

如何在单元测试时忽略这些属性?

+1

如果这样,你违反了单一责任原则是这样的。当您应该解决原因时,您正试图治疗症状。 –

+0

@HimBromBeere我正在测试'SomeMethod',并且此方法具有一些评估全局安全信息的属性(例如,如果用户已登录并且有东西)。然而,在单元测试中没有这样的信息,所以测试失败了,我无法测试该方法,明白了吗? – RafaelC

+0

@DavidL你能再详细一点吗? – RafaelC

我想我明白你要在这里做什么,但它不适用于Mocks,因为即使你创建了一个模拟SomeClass,你也必须模拟SomeMethod函数 - 你不能使用真正的!

这意味着你没有测试它,只是测试它的模拟版本。

但是,为什么不试试这个没有Mocks?

您可以使SomeOtherMethod为虚拟,然后子集SomeClass仅用于此测试。 然后,您可以编写任何您喜欢的SomeOtherMethod函数的重写;当你打电话给真实的SomeClass.SomeMethod时,它会调用该覆盖版本。

即(对不起,C#这样做是我的VB是生锈)假设SomeClass看起来是这样,选择一个故意无用的功能,以免混淆:

public class SomeClass 
{ 
    public virtual int SomeMethod() 
    { 
     return SomeOtherMethod()/2; 
    } 

    protected virtual SomeOtherMethod() 
    { 
     return [some crazy maths] 
    } 
} 

你想测试SomeMethod正确返回一半是SomeOtherMethod

所以,现在你可以做到这一点,在测试项目:

public class SomeClassTestDouble: SomeClass 
{ 
    protected override int SomeOtherMethod() 
    { 
     return 2; 
    } 
} 

那么在您的测试:

var sut = new SomeClassTestDouble(); 
var expected = 1; 
var actual = sut.SomeMethod(); 
Assert.Equal(expected, actual) 

现在你已经测试了SomeMethod按预期工作,没有任何嘲讽。事实上很多人会争辩说,除非你跨越了架构或系统边界,否则你更喜欢Mocks上的测试双打(包括存根)。我不会说如果我同意或不一般,但在这种情况下,我认为最好不要模仿。

注意事项

请记住re。属性 - 他们不应该做任何事情直到系统的其他部分告诉他们做某件事。如果系统的这一部分没有运行(即在测试过程中),那么这些属性应该是完全惰性的。如果他们不是,那么我倾向于看看你的单元测试项目,并确保你不会意外地运行诸如运行时安全框架之类的“实时”内容或其他东西