模拟moq,尝试将对象传递给具有多个参数的构造函数

汗88

我正在尝试模拟一种返回IEnumerable数据集(如所有代码列表)的方法。

有一个接口ISystemService.cs包含此方法,一个名为SystemService.cs的服务类具有方法定义。

被测系统为:

 public static class CacheKeys
    {
      public const string ALLCURRENCYCODES = "CurrencyCodes";
    }
 public interface ICacheManager
    {
        T Get<T>(string key);
        void Set(string key, object data, int cacheTime);
        void Clear();
    }
public interface ISessionManager
{
}
public interface IApplicationSettings
    {
        string LoggerName { get; }
        int CacheTimeout { get; }
    }
public class EFDbContext : DbContext
    {
    public DbSet<CurrencyCode> CurrencyCodes { get; set; }
    }
public class CurrencyCode 
    {
        public string Code { get; set; }
        public string Description { get; set; }
        public decimal CurrencyUnit { get; set; }
        public int? DecimalPlace { get; set; }
        public string BaseCurrencyCode { get; set; }
    }   
public interface ISystemService
    {
        IEnumerable<CurrencyCode> GetAllCurrencyCodes();
    }
//SystemService.cs
public class SystemService : ISystemService
    {

        private readonly EFDbContext db;
        private readonly ICacheManager cacheManager;
        private readonly ISessionManager sessionManager;
        private readonly IApplicationSettings appSettings;

        public SystemService(EFDbContext dbContext, ICacheManager cacheManager, ISessionManager sessionManager, IApplicationSettings appSettings)
        {
            db = dbContext;
            this.cacheManager = cacheManager;
            this.sessionManager = sessionManager;
            this.appSettings = appSettings;
        }
      public IEnumerable<CurrencyCode> GetAllCurrencyCodes()
        {
            var allCurrencyCodes = cacheManager.Get<IEnumerable<CurrencyCode>>(CacheKeys.ALLCURRENCYCODES);

            if (allCurrencyCodes == null)
            {
                allCurrencyCodes = db.CurrencyCodes.ToList();

                cacheManager.Set(CacheKeys.ALLCURRENCYCODES, allCurrencyCodes, appSettings.CacheTimeout);
            }

            return allCurrencyCodes;
        }

测试方法

[TestMethod]
        public void testCacheMiss()
        {
            List<CurrencyCode> currencycodes = new List<CurrencyCode>()
         {
            new CurrencyCode(){Id = 1, Code = "IND", Description = "India"},
            new CurrencyCode(){Id = 2, Code = "USA", Description = "UnitedStates"},
            new CurrencyCodes(){Id = 3, Code = "UAE", Description = "ArabEmirates"}
         };
            var mockEfContext = new Mock<EFDbContext>();
            var mockCacheManager = new Mock<ICacheManager>();
            var mockSessionManager = new Mock<ISessionManager>();
            var mockAppSettings = new Mock<IApplicationSettings>();

            // Setups for relevant methods of the above here, e.g. to test a cache miss
            mockEfContext.SetupGet(x => x.CurrencyCodes)
               .Returns(currencycodes); // Canned currencies
            mockCacheManager.Setup(x => x.Get<IEnumerable<CurrencyCode>>(It.IsAny<string>()))
               .Returns<IEnumerable<CurrencyCodes>>(null); // Cache miss

            // Act
            var service = new SystemService(mockEfContext.Object, mockCacheManager.Object,
               mockSessionManager.Object, mockAppSettings.Object);
            var codes = service.GetAllCodes();

            // Assert + Verify
            mockCacheManager.Verify(x => x.Get<IEnumerable<CurrencyCodes>>(
               It.IsAny<string>()), Times.Once, "Must always check cache first");
            mockEfContext.VerifyGet(x => x.CurrencyCodes,
               Times.Once, "Because of the simulated cache miss, must go to the Db");
            Assert.AreEqual(currencycodes.Count, codes.Count(), "Must return the codes as-is");

由于定义的构造函数不接受一个参数,如何将对象作为参数传递?请指教

斯图尔特

如果CodeService正在测试中,那么您想嘲笑其依赖关系,而不是其CodeService自身。

您需要为构造函数的Mock所有依赖项CodeService提供,即:

     var currencycodes = new List<SomeCodes>
     {
        new CurrencyCodes(){Id = 1, Code = "IND", Description = "India"},
        new CurrencyCodes(){Id = 2, Code = "USA", Description = "UnitedStates"},
        new CurrencyCodes(){Id = 3, Code = "UAE", Description = "ArabEmirates"}
     };
     var mockEfContext = new Mock<EFDbContext>();
     var mockCacheManager = new Mock<ICacheManager>();
     var mockSessionManager = new Mock<ISessionManager>();
     var mockAppSettings = new Mock<IApplicationSettings>();

     // Setups for relevant methods of the above here, e.g. to test a cache miss
     mockEfContext.SetupGet(x => x.SomeCodes)
        .Returns(currencycodes); // Canned currencies
     mockCacheManager.Setup(x => x.Get<IEnumerable<SomeCodes>>(It.IsAny<string>()))
        .Returns<IEnumerable<SomeCodes>>(null); // Cache miss

     // Act
     var service = new CodeService(mockEfContext.Object, mockCacheManager.Object,
        mockSessionManager.Object, mockAppSettings.Object);
     var codes = service.GetAllCodes();

     // Assert + Verify
     mockCacheManager.Verify(x => x.Get<IEnumerable<SomeCodes>>(
        It.IsAny<string>()), Times.Once, "Must always check cache first");
     mockEfContext.VerifyGet(x => x.SomeCodes,
        Times.Once, "Because of the simulated cache miss, must go to the Db");
     Assert.AreEqual(currencycodes.Count, codes.Count(), "Must return the codes as-is");

编辑但是,如果您的意思是代码的下一层正在测试中,则主体是相同的:

var mockCodeService = new Mock<ICodeService>();
mockCodeService.Setup(x => x.GetAllCodes())
    .Returns(currencycodes); // Now we don't care whether this is from cache or db 

var higherLevelClassUsingCodeService = new SomeClass(mockCodeService.Object);
higherLevelClassUsingCodeService.DoSomething();

mockCodeService.Verify(x => x.GetAllCodes(), Times.Once); // etc

编辑2
我已经修复了代码中的几个拼写错误,并假设CurrencyCodes继承SomeCodes并且您的缓存键是一个字符串,并通过相应的缓存未命中单元测试将其推到Git Gist上(我使用过NUnit,但在这里并没有实际意义)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

将ninject绑定对象传递给必须具有0参数的构造函数的类

无法将对象传递给Typescript中的构造函数

通过构造函数将对象传递给多个片段是一种不好的做法吗?

将对象传递给没有参数的片段

将对象传递给函数时,如何防止模板化构造函数将类作为参数

将对象传递给函数方法

将对象传递给PowerShell函数

将对象传递给事件函数

将对象作为参数传递给构造函数?

C ++通过引用将对象传递给函数,其构造函数被调用

将对象传递给Lambda std :: thread(C ++)中的函数:尝试使用已删除的函数

是否可以将Moq对象传递给C#类构造函数?

使用structuremap在运行时将对象传递给类构造函数

typescript,如何将对象传递给类的构造函数以进行实例化

C#静态类:我应该将对象传递给构造函数吗?

如何在angular 2/4 app的NgModule中将对象传递给服务构造函数

使用PHPUnit将模拟对象传递给父构造函数时发生TypeError

如何将具有关联作用的类似哈希的对象传递给期望哈希的构造函数?

将对象传递给函数调用中的函数

将对象数组传递给构造函数

将对象传递给 URL 搜索参数

将对象传递给 Datagrid 命令参数

在没有模型绑定的情况下将对象传递给路由参数

如何将对象传递给CasperJS函数

如何将对象传递给单独的函数-Python

将对象传递给R中的generate()评估的函数

将对象传递给Lua函数始终引用自身

在jQuery中将对象传递给回调函数

如何将对象传递给C ++中的函数?