gpt4 book ai didi

c# - 有什么方法可以模拟结构以在单元测试下获取类?

转载 作者:太空宇宙 更新时间:2023-11-03 12:06:22 25 4
gpt4 key购买 nike

我有一个类正在尝试进行单元测试。该类将结构公开为公共(public)属性。该结构还有一些公共(public)方法(比结构中的方法做的更多)。我无法更改结构(我不拥有该代码,目前风险太大)。

Mock 不适用于值类型。有没有办法有效地“模拟结构”?

public class SystemUnderTest
{
public FragileStructCantChange myStruct {get; set;}

public string MethodUnderTest()
{
if(myStruct.LongRunningMethod() == "successful")
return "Ok";
else
return "Fail";
}
}

public struct FragileStructCantChange
{
public string LongRunningMethod()
{
var resultString = DoStuff(); //calls other subsystems
return resultString;
}
}

最佳答案

通过一个称为"boxing" 的过程,通过一个接口(interface)引用一个结构有效地将它变成一个引用类型。 .装箱结构可能会导致行为发生一些细微的变化,您应该这样做 read about在做出决定之前。

另一种选择是在结构和被测代码之间添加一些间接。一种方法是添加一个以指定测试值。

public class SystemUnderTest
{
public FragileStructCantChange myStruct { get; set; }

// This value can be overridden for testing purposes
public string LongRunningMethodOverride { get; set; }

public string MethodUnderTest()
{
// Call the indirect Func instead of referencing the struct directly
if (LongRunningMethod() == "successful")
return "Ok";
else
return "Fail";
}

private string LongRunningMethod()
=> LongRunningMethodOverride ?? myStruct.LongRunningMethod();
}

public class Tests
{

[Fact]
public void TestingSideDoor()
{
var sut = new SystemUnderTest();

// Override the func to supply any test data you want
sut.LongRunningMethodOverride = "successful";

Assert.Equal("Ok", sut.MethodUnderTest());
}
}

另一种方法是公开一个可覆盖的函数指针...

public class SystemUnderTest
{
public FragileStructCantChange myStruct { get; set; }

// This Func can be overridden for testing purposes
public Func<string> LongRunningMethod;

public SystemUnderTest() {
LongRunningMethod = () => myStruct.LongRunningMethod();
}

public string MethodUnderTest()
{
// Call the indirect Func instead of referencing the struct directly
if (LongRunningMethod() == "successful")
return "Ok";
else
return "Fail";
}
}

public class Tests
{

[Fact]
public void TestingSideDoor()
{
var sut = new SystemUnderTest();

// Override the func to supply any test data you want
sut.LongRunningMethod = () => "successful";

Assert.Equal("Ok", sut.MethodUnderTest());
}
}

另一种选择是使用虚方法,它可以由子类或模拟框架(在本例中为 Moq)伪造...


public class SystemUnderTest
{
public FragileStructCantChange myStruct { get; set; }

// This method can be overridden for testing purposes
public virtual string LongRunningMethod()
=> myStruct.LongRunningMethod();

public string MethodUnderTest()
{
// Call the indirect method instead of referencing the struct directly
if (LongRunningMethod() == "successful")
return "Ok";
else
return "Fail";
}
}

public class Tests
{

[Fact]
public void TestingSideDoor()
{
var sut = new Mock<SystemUnderTest>();

// Override the method to supply any test data you want
sut.Setup(m => m.LongRunningMethod())
.Returns("successful");

Assert.Equal("Ok", sut.Object.MethodUnderTest());
}
}

我不会说这些选项中的任何一个都很好,在将这种后门放入共享库之前,我会认真考虑安全性。如果可行,接口(interface)通常更可取。

不过,这种方法是可行的,而且我认为当您面对不想进行侵入式重构的测试不友好代码时,这可能是一个公平的折衷方案。

关于c# - 有什么方法可以模拟结构以在单元测试下获取类?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54718078/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com