Используя Moq метод Start () продолжает перенастраивать нулевой объект - PullRequest
0 голосов
/ 09 ноября 2019

У меня возникают проблемы с выяснением, почему я не могу проверить свою переменную 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);
}

Если это помогает, реализация Concrete работает просто отлично, и этот тест выглядит следующим образом:

    [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

1 Ответ

2 голосов
/ 10 ноября 2019

Вы неправильно выполнили настройку.

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>()))

Вторая проблема заключается в том, что возвращаемое значение явно равно нулю. It.IsAny<T>() всегда возвращает значение по умолчанию для T. Все методы It используются только для сопоставления аргументов в выражении Setup. Если вы используете их вне выражения установки, вы просто получите значение по умолчанию для универсального аргумента, который в данном случае является нулевым значением. Обидно, что библиотека Moq не делает это неправильное использование громким сообщением об ошибке. Следовательно, вам нужно будет указать фактический экземпляр RemoteWebDriver в качестве возвращаемого значения. (Или, если вы можете отделить реализацию от конкретного конкретного типа, вы можете просто вернуть что-то, что реализует IWebDriver.)

Это значение может быть другим Mock-объектом, потенциально, но оно должно быть чем-то, что вы 'либо вы создали заранее, либо что-то, что может быть создано с помощью обратного вызова Returns.

Правильная настройка может выглядеть примерно так:

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 экземпляр в результате. Если у этого есть нежелательные побочные эффекты (такие как создание окна Chrome), вы можете подумать об изменении своей стратегии с использования конкретного конкретного типа на некоторый интерфейс или абстрактный класс. Если вы это сделаете, настройка может выглядеть примерно так:

var mockDriver = new Mock<IWebDriver>();
dummyManager.Setup(x => x.CreateRemoteWebDriver(It.IsAny<ChromeOptions>()))
            .Returns(mockDriver.Object);
...