我们的React-Redux应用程序使用create-react-app。我们正在尝试将Jest / Enzyme / redux-mock-store应用于大型代码库。我们的src / store.js文件是标准的react-redux脚本,用于运行reducers并构造初始状态。这个src / store.js是解决问题的关键。
问题是,当我们开始进行jest测试运行时,jest加载src / store.js 7次,然后(大约)为每个测试加载一次。 我必须抑制这种情况,并且不知道如何解决。我必须抑制的原因是,它始终使商店处于初始状态,并且有一个关键的AppConfig属性在该商店中,必须填充该商店,以防止因开玩笑而停止的javascript错误。我已经有一个函数,该函数返回模拟存储以供提供程序使用。那很好。但是我们的组件会从Constructor(),componentDidMount()等调用到api函数。这些api函数看不到从Provider删除的状态。相反,api函数会执行以下操作:
// AppConfig is an immutable Map
const { AppConfig } = store.getState();
const stuff = AppConfig.get(‘stuff’).toJS();
这是一个JS错误,因为AppConfig为空,并且toJS()在未定义时被调用。 (这在运行时永远不会成为问题,因为在没有准备好AppConfg的情况下我们不构造任何组件。)有两种解决方案,涉及到重构我可以做的App。但我宁愿弄清楚如何正确地使用玩笑。我该如何提供模拟redux状态而又不会因玩笑的src / store.js重复加载而使它瘫痪?
这真杀了我。在Jest,create-react-app或???中是什么?启动这些不必要的src / store.js负载?如何覆写?是否存在导致玩笑而不是src / store.js的配置?
答案 0 :(得分:0)
我想出了自己的问题。如果其他新手开玩笑会从我的愚蠢中受益,将会在这里发布。
Jest不会加载src / store.js。罪魁祸首是我的浅层组件测试,因为组件具有如下语句:
#import "UnityAppController.h"
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <AuthenticationServices/AuthenticationServices.h>
extern UIViewController *UnityGetGLViewController();
@interface SWA:UIViewController<ASAuthorizationControllerDelegate,ASAuthorizationControllerPresentationContextProviding>
@end
@implementation SWA
- (instancetype)init
{
self = [super init];
if (self) {
NSLog(@"Initialize SWA:%s", __FUNCTION__);
[self observeAppleSignInState];
}
return self;
}
//Alert
+(void)alertView:(NSString*)title addMessage:(NSString*) message
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:title
message:message preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *defaultAction = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:nil];
[alert addAction:defaultAction];
[UnityGetGLViewController() presentViewController:alert animated:YES completion:nil];
}
//Sign in with apple
-(void)SignInWithApple
{
//We can its iOS 13 +
if (@available(iOS 13.0, *)) {
// A mechanism for generating requests to authenticate users based on their Apple ID.
ASAuthorizationAppleIDProvider *appleIDProvider = [ASAuthorizationAppleIDProvider new];
// Creates a new Apple ID authorization request.
ASAuthorizationAppleIDRequest *request = appleIDProvider.createRequest;
// The contact information to be requested from the user during authentication.
request.requestedScopes = @[ASAuthorizationScopeFullName, ASAuthorizationScopeEmail];
// A controller that manages authorization requests created by a provider.
ASAuthorizationController *controller = [[ASAuthorizationController alloc] initWithAuthorizationRequests:@[request]];
// A delegate that the authorization controller informs about the success or failure of an authorization attempt.
controller.delegate = self;
// A delegate that provides a display context in which the system can present an authorization interface to the user.
controller.presentationContextProvider = self;
// starts the authorization flows named during controller initialization.
[controller performRequests];
}
}
#pragma mark - Delegate
//! Tells the delegate from which window it should present content to the user.
- (ASPresentationAnchor)presentationAnchorForAuthorizationController:(ASAuthorizationController *)controller API_AVAILABLE(ios(13.0)){
NSLog(@"window:%s", __FUNCTION__);
return UnityGetGLViewController().view.window;
}
-(void)observeAppleSignInState {
NSLog(@"Watching SWA:%s", __FUNCTION__);
if (@available(iOS 13.0, *)) {
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self selector:@selector(handleSignInWithAppleStateChanged:) name:ASAuthorizationAppleIDProviderCredentialRevokedNotification object:nil];
}
}
- (void)handleSignInWithAppleStateChanged:(id)noti {
NSLog(@"%s", __FUNCTION__);
NSLog(@"%@", noti);
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithAuthorization:(ASAuthorization *)authorization API_AVAILABLE(ios(13.0)){
NSLog(@"%s", __FUNCTION__);
NSLog(@"%@", controller);
NSLog(@"%@", authorization);
NSLog(@"authorization.credential:%@", authorization.credential);
NSMutableString *mStr = [NSMutableString string];
if ([authorization.credential isKindOfClass:[ASAuthorizationAppleIDCredential class]]) {
// ASAuthorizationAppleIDCredential
ASAuthorizationAppleIDCredential *appleIDCredential = authorization.credential;
NSString *user = appleIDCredential.user;
[mStr appendString:user?:@""];
NSString *familyName = appleIDCredential.fullName.familyName;
[mStr appendString:familyName?:@""];
NSString *givenName = appleIDCredential.fullName.givenName;
[mStr appendString:givenName?:@""];
NSString *email = appleIDCredential.email;
[mStr appendString:email?:@""];
NSLog(@"mStr:%@", mStr);
[mStr appendString:@"\n"];
} else if ([authorization.credential isKindOfClass:[ASPasswordCredential class]]) {
ASPasswordCredential *passwordCredential = authorization.credential;
NSString *user = passwordCredential.user;
NSString *password = passwordCredential.password;
[mStr appendString:user?:@""];
[mStr appendString:password?:@""];
[mStr appendString:@"\n"];
NSLog(@"mStr:%@", mStr);
} else {
mStr = [@"check" mutableCopy];
}
}
- (void)authorizationController:(ASAuthorizationController *)controller didCompleteWithError:(NSError *)error API_AVAILABLE(ios(13.0)){
NSLog(@"%s", __FUNCTION__);
NSLog(@"error :%@", error);
NSString *errorMsg = nil;
switch (error.code) {
case ASAuthorizationErrorCanceled:
errorMsg = @"ASAuthorizationErrorCanceled";
break;
case ASAuthorizationErrorFailed:
errorMsg = @"ASAuthorizationErrorFailed";
break;
case ASAuthorizationErrorInvalidResponse:
errorMsg = @"ASAuthorizationErrorInvalidResponse";
break;
case ASAuthorizationErrorNotHandled:
errorMsg = @"ASAuthorizationErrorNotHandled";
break;
case ASAuthorizationErrorUnknown:
errorMsg = @"ASAuthorizationErrorUnknown";
break;
}
NSMutableString *mStr = [NSMutableString string];
[mStr appendString:errorMsg];
[mStr appendString:@"\n"];
NSLog(@"mStr:%@", mStr);
if (errorMsg) {
return;
}
if (error.localizedDescription) {
NSMutableString *mStr = [NSMutableString string];
[mStr appendString:error.localizedDescription];
[mStr appendString:@"\n"];
NSLog(@"mStr:%@", mStr);
}
NSLog(@"controller requests:%@", controller.authorizationRequests);
}
//If sign in with apple available
+(bool)CanSingIn
{
if (@available(iOS 13.0, *)) {
return true;
}else{
return false;
}
}
extern "C"
{
void _ShowAlert(const char *title, const char *message)
{
SWA *classObject = [[SWA alloc] init];
[classObject SignInWithApple];
// [SWA alertView:[NSString stringWithUTF8String:title] addMessage:[NSString stringWithUTF8String:message]];
}
bool canSignIn(){
return [SWA CanSingIn];
}
}
@end
从组件对api的调用如下:
import StuffService from '../../api/stuff';
但是在定义StuffService的es6模块中,顶部有类似的内容:
// e.g. from componentDidMount
StuffService.get.myRequest();
这就是导致src / store保持运行的原因。将研究Jest的Manual Mocks作为解决方案。