如何使用异步调用对@IBAction进行单元测试

时间:2023-01-13 10:08:16

In the following code, I want to test whether "DisplayHelper.displayAlert" has been called. I am dependency-injecting DisplayHelper and AuthService mock objects, and using PromiseKit

在下面的代码中,我想测试是否“DisplayHelper”。displayAlert”被称为。我是依赖注入DisplayHelper和AuthService模拟对象,并使用PromiseKit。

In My ViewController:

在我ViewController:

@IBAction func submitButtonPressed(sender: AnyObject) {
    AuthService.updateUser(["zipcode": self.zipcodeTextField.text!])
        .then { user -> Void in
             // sucess code
        }.error { error -> Void in
            self.DisplayHelper.displayAlert("Zipcode Not Found", message: "We can't find that zipcode... please try again.", callingViewController: self)
        }
}

Here are the not-working tests:

以下是不工作的测试:

func testSubmitButtonServerCantFindZipcode() {
    vc.zipcodeTextField.text = "00000"
    vc.submitButtonPressed(self)

    // called AuthService    (passes)
    XCTAssertEqual(authServiceMock.updateUserCalled, true)

    // called displayAlert (fails because tests run before DisplayAlert is called)
    XCTAssertEqual(displayHelperMock.displayAlertCalled, true)
}

How do I get the tests to wait for all of the code to execute before the assertions?

如何让测试在断言之前等待所有代码执行?

1 个解决方案

#1


2  

When testing asynchronous code with XCTest you need to use XCTestExpectation.

在使用XCTest测试异步代码时,您需要使用xctestexpect。

You can rewrite the test code like this:

您可以这样重写测试代码:

let e = expectationWithDescription("display alert")
waitForExpectationsWithTimeout(3) { error in
    XCTAssertEqual(displayHelperMock.displayAlertCalled, true)
}

Now the only missing piece to make the test work is finding a place where to call expectation.fulfill(). The most appropriate place would be in your AuthService mock, after the success and failure callbacks are run.

现在,使测试工作有效的惟一缺失的部分是找到一个可以调用expect . fulfillment()的地方。最合适的位置是在运行成功和失败回调之后的AuthService mock中。

If I can suggest you something though, writing tests that asser whether certain methods have been called is not a safe approach to testing, as you are just testing implementation rather than behaviour.

如果我可以向您推荐一些东西,那么,编写一些测试来测试那些被调用的方法是不是安全的测试方法,因为您只是测试实现而不是行为。

What could be a better approach is to test the two componets independently. TestAuthService making sure that both the success and failure path execute as expected, and the DisplayHelper to make sure that the alert view is actually added to the view hierarchy.

一个更好的方法是独立地测试这两个组件。TestAuthService确保成功路径和失败路径都按预期执行,并确保将警报视图实际添加到视图层次结构中。

This article could be a useful place to start to find out how unit test alerts, and this post is a good read on why and how to avoid mocks.

这篇文章可能是了解单元测试警报的一个有用的地方,这篇文章是关于为什么以及如何避免模拟的一个很好的阅读。

#1


2  

When testing asynchronous code with XCTest you need to use XCTestExpectation.

在使用XCTest测试异步代码时,您需要使用xctestexpect。

You can rewrite the test code like this:

您可以这样重写测试代码:

let e = expectationWithDescription("display alert")
waitForExpectationsWithTimeout(3) { error in
    XCTAssertEqual(displayHelperMock.displayAlertCalled, true)
}

Now the only missing piece to make the test work is finding a place where to call expectation.fulfill(). The most appropriate place would be in your AuthService mock, after the success and failure callbacks are run.

现在,使测试工作有效的惟一缺失的部分是找到一个可以调用expect . fulfillment()的地方。最合适的位置是在运行成功和失败回调之后的AuthService mock中。

If I can suggest you something though, writing tests that asser whether certain methods have been called is not a safe approach to testing, as you are just testing implementation rather than behaviour.

如果我可以向您推荐一些东西,那么,编写一些测试来测试那些被调用的方法是不是安全的测试方法,因为您只是测试实现而不是行为。

What could be a better approach is to test the two componets independently. TestAuthService making sure that both the success and failure path execute as expected, and the DisplayHelper to make sure that the alert view is actually added to the view hierarchy.

一个更好的方法是独立地测试这两个组件。TestAuthService确保成功路径和失败路径都按预期执行,并确保将警报视图实际添加到视图层次结构中。

This article could be a useful place to start to find out how unit test alerts, and this post is a good read on why and how to avoid mocks.

这篇文章可能是了解单元测试警报的一个有用的地方,这篇文章是关于为什么以及如何避免模拟的一个很好的阅读。