gpt4 book ai didi

c# - 请问我如何对这种方法进行单元测试?

转载 作者:行者123 更新时间:2023-11-30 18:24:14 26 4
gpt4 key购买 nike

我在尝试对该方法进行单元测试时遇到问题。首先对我来说很清楚,但后来我很难理解如何有效地将我的数组注入(inject)/模拟到 bdcontext

public class UrlValidation: AbstractValidator<UrlShortenerModel> 
{
Uri uriResult;
private EFDbContext context;
.....

public bool notExist(string url)
{
//Check if The Url Exist . This is to stop replication of Urls.
bool exist = context.Urls.Any(x => x.OriginalUrl == url);

return (exist == false);
}
...

}

我想测试 notExist 方法。我从下面开始,然后坚持如何模拟我的上下文对类的值(value)?有什么方法可以表示或模拟上下文吗?我正在使用最小起订量来模拟我的虚拟数据,但我只是看不到这里的方式。而且它不是 Controller 类。

 public void Should_know_if_Url_Exist_or_Not()
{
ArrayList arr = new ArrayList();
arr.AddRange(new Url[]
{
new Url{ UrlId = 0, UrlCode = "TYUR", OriginalUrl="https://fluentvalidation.com", IpAddress="127.0.0.1", PostedDate = DateTime.Now},
new Url{ UrlId = 1, UrlCode = "TwUR", OriginalUrl="https://facebook.com", IpAddress="127.0.0.1", PostedDate = DateTime.Now},
new Url{ UrlId = 2, UrlCode = "TkUR", OriginalUrl="https://youtube.com/", IpAddress="127.0.0.1", PostedDate = DateTime.Now}
});


Assert.IsTrue(val.notExist("https://www.youtube.com/"));
Assert.IsFalse(val.notExist("https://www.facebook.com/"));

}

更新

当我将测试更改为

 [TestMethod]
public void Should_know_if_Url_Exist_or_Not()
{
Mock<IUrlsRepository> mock = new Mock<IUrlsRepository>();
mock.Setup(u => u.Urls).Returns(new Url[] {
new Url{ UrlId = 0, UrlCode = "TYUR", OriginalUrl="https://fluentvalidation.com", IpAddress="127.0.0.1", PostedDate = DateTime.Now},
new Url{ UrlId = 1, UrlCode = "TwUR", OriginalUrl="https://facebook.com", IpAddress="127.0.0.1", PostedDate = DateTime.Now},
new Url{ UrlId = 2, UrlCode = "TkUR", OriginalUrl="https://youtube.com/", IpAddress="127.0.0.1", PostedDate = DateTime.Now}
}.AsQueryable());



var validator = new UrlValidation(mock.Object);


Assert.IsTrue(validator.notExist("https://www.youtuberre.com/"));
Assert.IsFalse(validator.notExist("https://www.facebook.com/"));

}

并将我的验证类修改为

public IUrlShortenersRepository context;
public UrlValidation(IUrlShortenersRepository repo)
{
context = repo;
...

我的测试没有问题,但是失败了。但我无法再次运行该项目,因为我的流利验证类需要一个我不确定要传递到哪里的参数。我在模型中设置验证类,如下所示

 [Validator(typeof(UrlValidation))]
public class UrlShortenerModel
{
//The Model for the Home form. The Url shortener form.
public string strUrl { get; set; }
public IEnumerable<Url> urlList { get; set; }

}

我不确定在哪里注入(inject)参数。

不过,当我检查下面提供的链接时,我得到了一个清晰的示例,因此将我的测试修改为

 [TestMethod]
public void Should_know_if_Url_Exist_or_Not()
{
var arr = new List<Url>
{
new Url{ UrlId = 0, UrlCode = "TYUR", OriginalUrl="https://fluentvalidation.com", IpAddress="127.0.0.1", PostedDate = DateTime.Now},
new Url{ UrlId = 1, UrlCode = "TwUR", OriginalUrl="https://facebook.com", IpAddress="127.0.0.1", PostedDate = DateTime.Now},
new Url{ UrlId = 2, UrlCode = "TkUR", OriginalUrl="https://youtube.com/", IpAddress="127.0.0.1", PostedDate = DateTime.Now}
}.AsQueryable();

var mockSet = new Mock<DbSet<Url>>();
mockSet.As<IQueryable<Url>>().Setup(m => m.Provider).Returns(arr.Provider);
mockSet.As<IQueryable<Url>>().Setup(m => m.Expression).Returns(arr.Expression);
mockSet.As<IQueryable<Url>>().Setup(m => m.ElementType).Returns(arr.ElementType);
mockSet.As<IQueryable<Url>>().Setup(m => m.GetEnumerator()).Returns(arr.GetEnumerator());

var fakeContext = new Mock<EFDbContext>();
fakeContext.Setup(ctx => ctx.Urls).Returns(mockSet.Object);

var validator = new UrlValidation();
validator.context = fakeContext.Object;


Assert.IsTrue(validator.notExist("https://www.youtube.com/"));
Assert.IsFalse(validator.notExist("https://www.facebook.com/"));

}

我在 fakeContext.Setup(ctx => ctx.Urls).Returns(mockSet.Object); 处抛出“system.notsupportedexception invalid setup on a non-virtual”错误。我怀疑我的 EFDContext 不能被覆盖,如下面的用户所解释的。我不知道如何解决这个问题。我的 EFDContext 类在上下文中声明如下。

namespace UrlShortener.Domain.Concrete
{
public class EFDbContext:DbContext
{
public DbSet<Url> Urls { get; set; }
}
}

然后我在这里将 EFDContext 的属性更改为 virtual

namespace UrlShortener.Domain.Concrete
{
public class EFDbContext:DbContext
{
public virtual DbSet<Url> Urls { get; set; }
}
}

我的测试现在抛出 system.TargetInvocationException WITH A 内部异常 “无法绑定(bind)到目标方法,因为它的签名或安全透明度与委托(delegate)类型不兼容。”。消息 'CaSTLe.Proxies.DbSet1Proxy' 的类型初始值设定项引发异常。`错误被抛出在

fakeContext.Setup(ctx => ctx.Urls).Returns(mockSet.Object);

最佳答案

通常,您通过使用某种形式的依赖注入(inject)(作为构造函数参数,使用公共(public) setter ,使用服务定位器,...)将 dbcontext 或任何其他昂贵/难以测试的依赖注入(inject)到被测类中.

通过这种方式,您可以为单元测试注入(inject)一个伪造的实现,该实现在方法调用上存有伪造的数据和/或伪造的期望。

你可以包一个薄的header interface围绕您的 EFDbContext 类进行单元测试,或者您可以只在真实的 EFDbContext 上创建一些虚拟属性,如 here 所解释的那样.

public void Should_know_if_Url_Exist_or_Not()
{
ArrayList arr = new ArrayList();
arr.AddRange(new Url[]
{
new Url{ UrlId = 0, UrlCode = "TYUR", OriginalUrl="https://fluentvalidation.com", IpAddress="127.0.0.1", PostedDate = DateTime.Now},
new Url{ UrlId = 1, UrlCode = "TwUR", OriginalUrl="https://facebook.com", IpAddress="127.0.0.1", PostedDate = DateTime.Now},
new Url{ UrlId = 2, UrlCode = "TkUR", OriginalUrl="https://youtube.com/", IpAddress="127.0.0.1", PostedDate = DateTime.Now}
});

var fakeContext = new Mock<EFDbContext>();
fakeContext
.Setup(ctx => ctx.Urls)
.Returns(arr);
var validator = new UrlValidation(fakeContext.Object);

Assert.IsTrue(val.notExist("https://www.youtube.com/"));
Assert.IsFalse(val.notExist("https://www.facebook.com/"));

}

关于c# - 请问我如何对这种方法进行单元测试?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31508087/

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