我有一个运行正常的测试,但我需要有关如何正确测试逻辑的指导。我对测试的理解是,应该在不与资源紧密耦合的情况下完成测试(这是进行模拟的地方),但是如果所有内容都经过模拟(尤其是返回结果),那么如何在不实例化一堆类的情况下正确地测试逻辑?
ValidateEmployeeConfigurationAsync
(如下)将返回RulesValidationResult
,这是我要声明的内容。因此,我可以回答我自己的问题,即如何更新存储库和服务-这是一种方法。是否有最佳实践来实现这一目标?感觉不对。
[TestMethod]
public async Task PassValidateEmployeeConfigurationTest()
{
//ARRANGE
const long employeeId = 200L;
const int configurationTypeId = (int) Constants.Configuration.ConfigurationTypes.User;
const bool enabled = true;
_ruleService = new Mock<IRuleService>();
_configurationService = new Mock<IConfigurationService>();
_ruleFacade = new Mock<IRuleFacade>();
_configurationService.Setup(x => x.GetByConfigurationNameAsync(It.IsAny<string>()))
.ReturnsAsync(GetConfigurations(enabled));
_ruleService.Setup(x => x.GetConfigRulesByEmployeeIdAsync(It.IsAny<long>()))
.ReturnsAsync(GetRules(enabled));
_ruleFacade.Setup(x =>
x.ValidateEmployeeConfigurationAsync(It.IsAny<long>(), It.IsAny<string>(), It.IsAny<int>()))
.ReturnsAsync(GetPassedValidationResult());
//ACT
var result = await
_ruleFacade.Object.ValidateEmployeeConfigurationAsync(employeeId, "TestConfiguration", configurationTypeId);
//ASSERT
Assert.IsNotNull(result);
Assert.AreEqual(true, result.PassedValidation);
}
public async Task<RulesValidationResult> ValidateEmployeeConfigurationAsync(long employeeId, string configurationName, int configurationTypeId = 6)
{
var key = GetDefaultKey(configurationName);
var rules = new List<Rule>();
var validationResult = new RulesValidationResult();
validationResult.Messages.Add("Configuartion not found", configurationName);
var configurations = await _configurationService.GetByConfigurationNameAsync(configurationName);
if (!configurations.Any())
return validationResult;
var configuration = configurations.FirstOrDefault(c => c.ConfigurationTypeId == configurationTypeId);
rules = await _ruleService.GetConfigRulesByEmployeeIdAsync(employeeId);
if (rules.Any() && configuration.ConfigurationSettings.Any())
{
var testTargets = new List<ConfigurationSetting>();
testTargets.AddRange(from setting in configuration.ConfigurationSettings
where setting.IsActive && setting.Key == key
select new ConfigurationSetting
{
ConfigurationId = setting.ConfigurationId,
Key = setting.Key,
Value = setting.Value
});
if (PassesRules(testTargets, rules))
{
var msg = $"{configurationName} passed rule validation";
validationResult.PassedValidation = true;
validationResult.Messages.Clear();
validationResult.Messages.Add("Passed", msg);
}
else
{
var msg = $"{configurationName} failed rule validation";
validationResult.Messages.Clear();
validationResult.Messages.Add("Failed", msg);
}
}
return validationResult;
}
答案 0 :(得分:0)
这就是我构建测试的方式,查看TestMethod
的先前版本以查看差异。在最初的问题中,如果测试的结构方式不正确,则测试将始终通过。
在此版本中,模拟了输入,模拟了依赖项,并设置了IOC容器,以便测试目标代码并将断言应用于生成的输出。
[TestMethod]
public async Task PassValidateEmployeeConfigurationTest()
{
//ARRANGE
const long employeeId = 200L;
const int configurationTypeId = (int) Constants.Configuration.ConfigurationTypes.User;
//need the IOC container
var unityContainer = new UnityContainer();
//Mock ALL the dependencies (services and repositories)
var ruleFacade = new Mock<IRuleFacade>();
var employeeConfigMapRepo = new Mock<IEmployeeConfigurationMapRepo>();
var ruleRepo = new Mock<IRuleRepo>();
var ruleService = new Mock<IRuleService>();
var configurationService = new Mock<IConfigurationService>();
var employeeConfigurationService = new Mock<IEmployeeConfigurationService>();
var organizationConfigurationService = new Mock<IOrganizationConfigurationService>();
var facilityConfigurationService = new Mock<IFacilityConfigurationService>();
var configurationSettingService = new Mock<IConfigurationSettingService>();
// configure the dependencies so that the proper inputs are available
configurationService.Setup(x => x.GetByConfigurationNameAsync(It.IsAny<string>()))
.ReturnsAsync(GetConfigurations(true));
employeeConfigMapRepo.Setup(x => x.GetAllByEmployeeIdAsync(It.IsAny<int>()))
.ReturnsAsync(GetEmployeeConfigMaps(true));
employeeConfigurationService.Setup(x => x.GetAllByEmployeeIdAsync(It.IsAny<long>()))
.ReturnsAsync(GetEmployeeConfigMaps(true));
ruleRepo.Setup(x => x.GetByConfigurationIdAsync(It.IsAny<int>()))
.ReturnsAsync(GetRules(true));
ruleService.Setup(x => x.GetConfigRulesByEmployeeIdAsync(It.IsAny<long>(), It.IsAny<string>()))
.ReturnsAsync(GetRules(true));
// help the IOC do its thing, map interfaces to Mocked objects
unityContainer.RegisterInstance<IRuleService>(ruleService.Object);
unityContainer.RegisterInstance<IRuleRepo>(ruleRepo.Object);
unityContainer.RegisterInstance<IConfigurationService>(configurationService.Object);
unityContainer.RegisterInstance<IEmployeeConfigurationService>(employeeConfigurationService.Object);
unityContainer.RegisterInstance<IOrganizationConfigurationService>(organizationConfigurationService.Object);
unityContainer.RegisterInstance<IFacilityConfigurationService>(facilityConfigurationService.Object);
unityContainer.RegisterInstance<IConfigurationSettingService>(configurationSettingService.Object);
unityContainer.RegisterInstance<IRuleFacade>(ruleFacade.Object);
// thanks to all the mocking, the facade method ValidateEmployeeConfigurationAsync can now be tested properly
var ruleHelper = unityContainer.Resolve<RuleFacade>();
//ACT
var result = await
ruleHelper.ValidateEmployeeConfigurationAsync(employeeId, _testConfigName, configurationTypeId);
//ASSERT
Assert.IsNotNull(result);
Assert.AreEqual(true, result.PassedValidation);
}