我有一个asp。net核心应用程序,该应用程序使用启动中定义的依赖项注入。应用程序的cs类:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration["Data:FotballConnection:DefaultConnection"]));
// Repositories
services.AddScoped<IUserRepository, UserRepository>();
services.AddScoped<IUserRoleRepository, UserRoleRepository>();
services.AddScoped<IRoleRepository, RoleRepository>();
services.AddScoped<ILoggingRepository, LoggingRepository>();
// Services
services.AddScoped<IMembershipService, MembershipService>();
services.AddScoped<IEncryptionService, EncryptionService>();
// new repos
services.AddScoped<IMatchService, MatchService>();
services.AddScoped<IMatchRepository, MatchRepository>();
services.AddScoped<IMatchBetRepository, MatchBetRepository>();
services.AddScoped<ITeamRepository, TeamRepository>();
services.AddScoped<IFootballAPI, FootballAPIService>();
这允许这样的操作:
[Route("api/[controller]")]
public class MatchController : AuthorizedController
{
private readonly IMatchService _matchService;
private readonly IMatchRepository _matchRepository;
private readonly IMatchBetRepository _matchBetRepository;
private readonly IUserRepository _userRepository;
private readonly ILoggingRepository _loggingRepository;
public MatchController(IMatchService matchService, IMatchRepository matchRepository, IMatchBetRepository matchBetRepository, ILoggingRepository loggingRepository, IUserRepository userRepository)
{
_matchService = matchService;
_matchRepository = matchRepository;
_matchBetRepository = matchBetRepository;
_userRepository = userRepository;
_loggingRepository = loggingRepository;
}
这很整洁。但当我想进行单元测试时,这就成了一个问题。因为我的测试库没有启动。cs,其中我设置依赖项注入。因此,将这些接口作为参数的类将仅为null。
namespace TestLibrary
{
public class FootballAPIService
{
private readonly IMatchRepository _matchRepository;
private readonly ITeamRepository _teamRepository;
public FootballAPIService(IMatchRepository matchRepository, ITeamRepository teamRepository)
{
_matchRepository = matchRepository;
_teamRepository = teamRepository;
在上面的代码中,在测试库中,_matchRepository和_teamRepository将为空。:(
我可以做一些类似配置服务的事情吗,在那里我在测试库项目中定义依赖注入?
您的控制器位于。net core从一开始就考虑了依赖项注入,但这并不意味着您需要使用依赖项注入容器。
给定一个更简单的类,如:
public class MyController : Controller
{
private readonly IMyInterface _myInterface;
public MyController(IMyInterface myInterface)
{
_myInterface = myInterface;
}
public JsonResult Get()
{
return Json(_myInterface.Get());
}
}
public interface IMyInterface
{
IEnumerable<MyObject> Get();
}
public class MyClass : IMyInterface
{
public IEnumerable<MyObject> Get()
{
// implementation
}
}
因此,在您的应用程序中,您正在使用startup.cs
中的依赖注入容器,它只不过提供了MyClass
的具体化,以便在遇到IMyInterface
时使用。然而,这并不意味着它是获取MyController
实例的唯一方法。
在单元测试场景中,您可以(并且应该)提供自己的IMyInterface实现(或mock/stub/false),如下所示:
public class MyTestClass : IMyInterface
{
public IEnumerable<MyObject> Get()
{
List<MyObject> list = new List<MyObject>();
// populate list
return list;
}
}
在您的测试中:
[TestClass]
public class MyControllerTests
{
MyController _systemUnderTest;
IMyInterface _myInterface;
[TestInitialize]
public void Setup()
{
_myInterface = new MyTestClass();
_systemUnderTest = new MyController(_myInterface);
}
}
因此,对于单元测试MyController
的范围,IMyInterface
的实际实现并不重要(也不应该重要),只有接口本身才重要。我们通过MyTestClass
提供了IMyInterface
的“假”实现,但您也可以使用类似于通过Moq
或RhinoMocks
的模拟来做到这一点。
总之,您实际上不需要依赖注入容器来完成测试,只需要一个单独的、可控制的、实现/模拟/存根/假的被测试类依赖项。
一种简单的方法是,我编写了一个通用依赖解析程序助手类,然后在单元测试类中构建了IWebHost。
通用依赖关系解析程序
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
public class DependencyResolverHelper
{
private readonly IWebHost _webHost;
/// <inheritdoc />
public DependencyResolverHelper(IWebHost webHost) => _webHost = webHost;
public T GetService<T>()
{
var serviceScope = _webHost.Services.CreateScope();
var services = serviceScope.ServiceProvider;
try
{
var scopedService = services.GetRequiredService<T>();
return scopedService;
}
catch (Exception e)
{
Console.WriteLine(e);
throw;
}
}
}
}
单元测试项目:
[TestFixture]
public class DependencyResolverTests
{
private DependencyResolverHelper _serviceProvider;
public DependencyResolverTests()
{
var webHost = WebHost.CreateDefaultBuilder()
.UseStartup<Startup>()
.Build();
_serviceProvider = new DependencyResolverHelper(webHost);
}
[Test]
public void Service_Should_Get_Resolved()
{
//Act
var YourService = _serviceProvider.GetService<IYourService>();
//Assert
Assert.IsNotNull(YourService);
}
}
虽然@Kritner的答案是正确的,但为了代码完整性和更好的DI体验,我更喜欢以下内容:
[TestClass]
public class MatchRepositoryTests
{
private readonly IMatchRepository matchRepository;
public MatchRepositoryTests()
{
var services = new ServiceCollection();
services.AddTransient<IMatchRepository, MatchRepositoryStub>();
var serviceProvider = services.BuildServiceProvider();
matchRepository = serviceProvider.GetService<IMatchRepository>();
}
}
问题内容: 我有一堂课要添加单元测试。该类具有多个构造函数,这些构造函数采用不同的类型并将其转换为规范形式,然后可以将其转换为其他类型。 实际上,它接受并转换为其他两种类型。 我正在尝试找出最合适的方法来测试这些构造函数。 应该有一个针对每个构造函数的测试和输出类型: 这导致许多不同的测试。如您所见,我正在努力命名它们。 应该有多个断言: 这有多个断言,这使我感到不舒服。它还正在测试getStri
好的,到目前为止还好。但是等等,突然A需要额外的输入,比如一个对它的构造至关重要的名为“amount”的整数。现在,我的A构造函数需要如下所示: 突然这个新参数干扰了注射。此外,即使这确实有效,我也无法在从提供者检索新实例时输入“金额”,除非我弄错了。这里有几件事我可以做,我的问题是哪一件是最好的? 我可以通过添加一个方法来重构A,该方法应该在构造函数之后调用。然而,这是很难看的,因为它迫使我推迟
问题内容: 在对Angular工厂进行单元测试(使用Karma + Jasmine)时,如何将存根依赖项注入到要测试的工厂中? 这是我的工厂: 实例化我的工厂时需要。 这是我的测试: 注意:我知道这允许用于控制器,但是我没有看到与之等效的工厂。 问题答案: 我知道有两种方法可以完成这样的事情: 使用和匿名模块注入模拟。 注入您要模拟的服务,并使用茉莉的间谍功能提供模拟值。 第二个选项仅在您确切知道
在我的ASP. NET Core应用程序中,我有一个具有多个构造函数的标记助手。当ASP. NET 5尝试解析类型时,这会在运行时导致以下错误: 在类型'MyNameSpace中发现了多个接受所有给定参数类型的构造函数。MyTagHelper'.应该只有一个适用的构造函数。 其中一个构造函数是无参数的,另一个有一些参数不是注册类型的参数。我希望它使用无参数构造函数。 有没有办法让ASP. NET
和另一个类: 在这种情况下,服务将按照预期注入到A类中。据我所知,你不能在a类中使用构造函数,否则注入将无法工作。有没有一种方法可以在a类中使用一个构造函数,同时注入服务?即: 在这种情况下,我得到的服务是空的,无论如何要解决这个问题?我希望能够从类型A中使用“new”创建一个对象,并注入服务,这可能吗?
我正试图在计算机上实现这个例子https://developer.android.com/jetpack/docs/guide.这就解释了Android应用程序的结构。 当我使用相同的代码时,我会出现以下错误。 我可以找出这个错误与 当我为ViewModel编写默认的零输入构造函数时,我得到了以下错误。 我想不出这个错误的原因和解决方法。