我在弄清楚为什么我无法测试我的driver
变量时遇到了麻烦,当我调用null
时,它不断返回Start()
。我基本上想访问该变量并对其进行测试。
我目前无法通过的测试:
[TestMethod]
public void Start_Default_IsChrome2()
{
var dummyManager = new Mock<IRemoteDriver>();
var mockDriver = new Mock<IWebDriver>();
dummyManager.Setup(x => x.CreateRemoteWebDriver(new ChromeOptions()))
.Returns(It.IsAny<RemoteWebDriver>());
var session = new SauceSession(dummyManager.Object);
//The Start() keeps returning a null object
var driver = session.Start();
var capabilities = driver.Capabilities;
capabilities.GetCapability("browserName").Should().Be("chrome");
}
要嘲笑的依赖性
public interface IRemoteDriver
{
IWebDriver CreateRemoteWebDriver(ChromeOptions chromeOptions);
}
被测对象
public SauceSession(IRemoteDriver driverManager)
{
remoteDriverManager = driverManager;
}
public RemoteWebDriver Start()
{
sauceUserName = Environment.GetEnvironmentVariable("SAUCE_USERNAME", EnvironmentVariableTarget.User);
sauceAccessKey = Environment.GetEnvironmentVariable("SAUCE_ACCESS_KEY", EnvironmentVariableTarget.User);
sauceOptions = new Dictionary<string, object>
{
["username"] = sauceUserName,
["accessKey"] = sauceAccessKey
};
var chromeOptions = new ChromeOptions
{
BrowserVersion = "latest",
PlatformName = "Windows 10",
UseSpecCompliantProtocol = true
};
chromeOptions.AddAdditionalCapability("sauce:options", sauceOptions, true);
//This keeps returning a null
return (RemoteWebDriver)remoteDriverManager.CreateRemoteWebDriver(chromeOptions);
}
如果有帮助,则具体实现可以正常工作,并且该测试如下所示:
[TestMethod]
public void Start_Default_IsChrome()
{
var session = new SauceSession();
var driver = session.Start();
var capabilities = ((RemoteWebDriver)driver).Capabilities;
capabilities.GetCapability("browserName").Should().Be("chrome");
}
除了我在这里设置的对象以外,其他所有东西都相同:
public SauceSession()
{
remoteDriverManager = new ConcreteRemoteWebDriver();
}
class ConcreteRemoteWebDriver : IRemoteDriver
{
public IWebDriver CreateRemoteWebDriver(ChromeOptions chromeOptions)
{
return new RemoteWebDriver(new Uri("https://ondemand.saucelabs.com/wd/hub"),
chromeOptions.ToCapabilities(), TimeSpan.FromSeconds(600));
}
}
这里是RemoteWebDriver:
public class RemoteWebDriver : IWebDriver, ISearchContext, IDisposable, IJavaScriptExecutor, IFindsById, IFindsByClassName, IFindsByLinkText, IFindsByName, IFindsByTagName, IFindsByXPath, IFindsByPartialLinkText, IFindsByCssSelector, ITakesScreenshot, IHasInputDevices, IHasCapabilities, IHasWebStorage, IHasLocationContext, IHasApplicationCache, IAllowsFileDetection, IHasSessionId, IActionExecutor
您未正确完成设置。
dummyManager.Setup(x => x.CreateRemoteWebDriver(new ChromeOptions()))
.Returns(It.IsAny<RemoteWebDriver>());
这里两件事:
您正在精确匹配new ChromeOptions()
的一个实例。在确定要返回哪个对象时,Moq将检查传递给CreateRemoteWebDriver
的参数是否与设置中提供的参数相同。
new ChromeOptions
{
BrowserVersion = "latest",
PlatformName = "Windows 10",
UseSpecCompliantProtocol = true
};
和
new ChromeOptions()
将得出相等的结果,表示此设置将不匹配。
您可能只是想像这样使用It.IsAny<ChromeOptions>()
dummyManager.Setup(x => x.CreateRemoteWebDriver(It.IsAny<ChromeOptions>()))
第二个问题是您的返回值显式为null。It.IsAny<T>()
始终返回T
的默认值。 It
方法都仅用于Setup
表达式内的参数匹配。如果在设置表达式之外使用它们,则将只获取通用参数的默认值,在这种情况下,该默认值为空值。 Moq库没有使这种不正确的用法成为大声的错误消息,这是很可惜的。因此,您需要提供RemoteWebDriver
的实际实例作为返回值。 (或者,如果您可以将实现与特定的具体类型分离,则可以返回实现IWebDriver
的东西。)
该值可能是另一个Mock对象,但是它必须是您提前创建的,或者可以通过Return回调创建的。
正确的设置可能类似于:
var mockDriver = new Mock<RemoteWebDriver>();
dummyManager.Setup(x => x.CreateRemoteWebDriver(It.IsAny<ChromeOptions>()))
.Returns(mockDriver.Object); //This could throw an exception if RemoteWebDriver needs arguments.
一个小警告是,您将实际上创建一个RemoteWebDriver
实例作为结果。如果这样做有不利的副作用(例如创建镶边窗口),则需要考虑将策略从使用特定的具体类型更改为某些接口或抽象类。如果这样做,则安装程序可能类似于以下内容:
var mockDriver = new Mock<IWebDriver>();
dummyManager.Setup(x => x.CreateRemoteWebDriver(It.IsAny<ChromeOptions>()))
.Returns(mockDriver.Object);