gpt4 book ai didi

asp.net-mvc - 在 ASP.NET MVC 测试项目中模拟静态方法

转载 作者:行者123 更新时间:2023-12-01 10:59:15 24 4
gpt4 key购买 nike

我有一个看起来像下面的方法

public List<Rajnikanth> GetRajnis()
{
string username = Utility.Helpers.GetLoggedInUserName();
return _service.GetRajni(username);
}

Utility.Helper 是一个静态类,公共(public)静态类助手{

public static String GetLoggedInUserName()
{
string username = "";
if (System.Web.HttpContext.Current.User.Identity.IsAuthenticated)
{
username = ((System.Web.Security.FormsIdentity)HttpContext.Current.User.Identity).Ticket.Name;
}
return username;

}

我想测试:GetRajnis()

我想模拟:GetLoggedInUserName()

所以我的测试方法看起来像...

[TestMethod]
public void TestGetRajnis()
{
SomeController s = new SomeController(new SomeService());
var data = s.GetRajnis();
Assert.IsNotNull(data);
}

如何模拟静态方法 GetLoggedInUserName() ?

最佳答案

最简单的方法:覆盖返回值

如果你想模拟一个返回值,那么这很简单。您可以修改 Utility.Helper 类以包含名为 OverrideLoggedInUserName 的属性。当有人调用 GetLogedInUserName() 时,如果设置了 override 属性,则返回,否则使用从 HttpContext 获取值的正常代码来获取返回值。

public static class Helper
{
// Set this value to override the return value of GetLoggedInUserName().
public static string OverrideLoggedInUserName { get; set; };

public static string GetLoggedInUserName()
{
// Return mocked value if one is specified.
if ( !string.IsNullOrEmpty( OverrideLoggedInUserName ) )
return OverrideLoggedInUserName;

// Normal implementation.
string username = "";
if ( System.Web.HttpContext.Current.User.Identity.IsAuthenticated )
{
username = ( (System.Web.Security.FormsIdentity)HttpContext.Current.User.Identity ).Ticket.Name;
}
return username;
}
}

这将有效地允许您覆盖返回值,从技术上讲,这不是一个模拟——它是一个 stub (根据 Martin Fowler 的优秀文章 Mocks Aren't Stubs)。这允许您 stub 返回值,但不允许您断言该方法是否被调用。无论如何,只要您只想操纵返回值,就可以正常工作。

下面是您将如何在测试中使用它。

[ TestMethod ]
public void TestGetRajnis()
{
// Set logged in user name to be "Bob".
Helper.OverrideLoggedInUserName = "Bob";

SomeController s = new SomeController( new SomeService() );
var data = s.GetRajnis();

// Any assertions...
}

这种设计确实有一个缺点。因为它是一个静态类,所以如果您设置覆盖值,它将保持设置直到您取消设置。所以一定要记得重新设置为null。

更好的方法:注入(inject)依赖

更好的方法可能是创建一个类来检索登录的用户名,并将其传递给 SomeController 的构造函数。我们称之为 dependency injection .这样,您可以将模拟实例注入(inject)其中进行测试,但在不测试时传递真实实例(从 HttpContext 获取用户)。这是一种更简洁明了的方法。此外,您可以利用所使用的任何模拟框架的所有功能,因为它们是专门为处理这种方法而设计的。这就是它的样子。

// Define interface to get the logged in user name.
public interface ILoggedInUserInfo
{
string GetLoggedInUserName();
}

// Implementation that gets logged in user name from HttpContext.
// This class will be used in production code.
public class LoggedInUserInfo : ILoggedInUserInfo
{
public string GetLoggedInUserName()
{
// This is the same code you had in your example.
string username = "";
if ( System.Web.HttpContext.Current.User.Identity.IsAuthenticated )
{
username = ( (System.Web.Security.FormsIdentity)HttpContext.Current.User.Identity ).Ticket.Name;
}
return username;
}
}

// This controller uses the ILoggedInUserInfo interface
// to get the logged in user name.
public class SomeController
{
private SomeService _service;
private ILoggedInUserInfo _userInfo;

// Constructor allows you inject an object that tells it
// how to get the logged in user info.
public SomeController( SomeService service, ILoggedInUserInfo userInfo )
{
_service = service;
_userInfo = userInfo;
}

public List< Rajnikanth > GetRajnis()
{
// Use the injected object to get the logged in user name.
string username = _userInfo.GetLoggedInUserName();
return _service.GetRajni( username );
}
}

这里是使用 Rhino Mocks 将 stub 对象注入(inject) Controller 的测试。

[ TestMethod ]
public void TestGetRajnis()
{
// Create a stub that returns "Bob" as the current logged in user name.
// This code uses Rhino Mocks mocking framework...
var userInfo = MockRepository.GenerateStub< ILoggedInUserInfo >();
userInfo.Stub( x => x.GetLoggedInUserName() ).Return( "Bob" );

SomeController s = new SomeController( new SomeService(), userInfo );
var data = s.GetRajnis();

// Any assertions...
}

这里的缺点是您不能从代码中的任何地方调用 Helper.GetLoggedInUserName(),因为它不再是静态的。但是,您不再需要在每次完成测试时都重新设置 stub 用户名。因为它不是静态的,所以它会自动重置。您只需为下一次测试重新创建它并设置新的返回值。

希望对您有所帮助。

关于asp.net-mvc - 在 ASP.NET MVC 测试项目中模拟静态方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12783277/

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