10

L'applicazione a pagina singola su cui sto lavorando ha una vista di accesso con due moduli: un modulo di accesso e un modulo di registrazione. La seguente specifica descrive i test per questi moduli. Sto usando Jasmine-jQuery 1.4.2.Test al gelsomino utilizzando .toHaveBeenCalledWith non riesce per il modulo di registrazione

// user_spec.js 

describe("User", function() { 

    var userController; 

    beforeEach(function() { 
    loadFixtures('menu.html'); 
    userController = new MyApp.User.Controller(); 
    }); 

    describe("LoginView", function() { 

    beforeEach(function() { 
     // Mock the $.ajax function to prevent XHR: 
     spyOn($, "ajax").andCallFake(function(params) {}); 
    }); 

    it("should pass email and password with the 'signInForm:submit' event.", function() { 
     var email = "[email protected]"; 
     var password = "Passw0rd"; 
     var callback = jasmine.createSpy("FormSubmitSpy"); 

     userController.loginView.$el.find("#signInEmail").val(email); 
     userController.loginView.$el.find("#signInPassword").val(password); 
     userController.loginView.bind("signInForm:submit", callback, this); 
     userController.loginView.ui.signInForm.trigger("submit"); 

     expect(callback).toHaveBeenCalledWith({ 
     email: email, 
     password: password 
     }); 
    }); 

    it("should pass name, email and password with the 'signUpForm:submit' event.", function() { 
     var name = "John Doe"; 
     var email = "[email protected]"; 
     var password = "Passw0rd"; 
     var callback = jasmine.createSpy("FormSubmitSpy"); 

     userController.loginView.$el.find("#signUpName").val(name); 
     userController.loginView.$el.find("#signUpMail").val(email); 
     userController.loginView.$el.find("#signUpPassword").val(password); 
     userController.loginView.$el.find("#signUpPasswordConfirmation").val(password); 
     userController.loginView.bind("signUpForm:submit", callback, this); 

     userController.loginView.ui.signUpForm.trigger("submit"); 

     expect(callback).toHaveBeenCalledWith({ 
     name: name, 
     email: email, 
     password: password, 
     password_confirmation: password 
     }); 
    }); 

    }); 

}); 

Il test per l'accesso in forma corre successo invece il test per il modulo di iscrizione non riesce.

Error: Expected spy FormSubmitSpy to have been called with \ 
    [ { name : 'John Doe', email : '[email protected]', \ 
    password : 'Passw0rd', password_confirmation : 'Passw0rd' } ] \ 
    but it was never called. 

    at new jasmine.ExpectationResult (http://localhost:3000/assets/jasmine.js?body=1:114:32) 
    at null.toHaveBeenCalledWith (http://localhost:3000/assets/jasmine.js?body=1:1235:29) 
    at null.<anonymous> (http://localhost:3000/assets/user_spec.js?body=1:233:24) 
    at jasmine.Block.execute (http://localhost:3000/assets/jasmine.js?body=1:1064:17) 
    at jasmine.Queue.next_ (http://localhost:3000/assets/jasmine.js?body=1:2096:31) 
    at jasmine.Queue.start (http://localhost:3000/assets/jasmine.js?body=1:2049:8) 
    at jasmine.Spec.execute (http://localhost:3000/assets/jasmine.js?body=1:2376:14) 
    at jasmine.Queue.next_ (http://localhost:3000/assets/jasmine.js?body=1:2096:31) 
    at jasmine.Queue.start (http://localhost:3000/assets/jasmine.js?body=1:2049:8) 
    at jasmine.Suite.execute (http://localhost:3000/assets/jasmine.js?body=1:2521:14) 

Utilizzando i moduli nell'applicazione non ci sono problemi. I dati vengono trasmessi Tutto funziona bene Solo il test no.

Soluzione

Il test è comunque successo quando ritardarne l'esecuzione.

_.defer(function() { 
    expect(callback).toHaveBeenCalledWith({ 
    name: name, 
    email: email, 
    password: password, 
    password_confirmation: password 
    }); 
}); 

Perché funziona e l'implementazione "normale" non riesce?


Ecco una semplificazione del caso specifico:

it("should evaluate true", function() { 
    var foo = false; 
    _.defer(function() { 
    foo = true; 
    }); 
    expect(foo).toBeTruthy(); 
}); 
+0

Cosa succede se si rimuove il test signInForm? O spostalo dopo il test di signupForm? –

+0

Forse qualcos'altro sta fermando l'evento e poi si riattiva dopo qualche azione. Sembra un po 'probabile in una sottomissione di modulo che non dovrebbe aggiornare la pagina. Se il fermo non si attiva in modo sincrono, allora questa spia fallirà. – fncomp

risposta

1

Il motivo che state vedendo questo problema è perché il callback è annidato in qualche altro metodo, probabilmente jQuery legano e spia di gelsomino avvolge direttamente sopra il tuo metodo così quando il test è impostato il tuo metodo non viene eseguito fino al prossimo tick.

Ho trovato questa pagina: http://trevmex.com/post/7017702464/nesting-spies-to-see-if-a-callback-in-a-deep-nest-has utile in quanto descrive il tuo problema e un potenziale lavoro in giro.

Tuttavia, ho scoperto che è meglio non testare necessariamente i callback in quanto possono essere considerati metodi privati. Forse puoi testare il suo risultato finale?

2

Il modo per fare la stessa cosa senza l'utilizzo di una funzione di sottolineatura per il differimento sarebbe il seguente Jasmine:

var flag = false; 
... 

runs(function() { 
    userController.loginView.ui.signInForm.trigger("submit"); 
    setTimeout(function() { flag = true; }, 1); 
} 

waitsFor(function() { 
    return flag; 
}, "Blah this should never happen", 10); 

runs(function() { 
    expect(callback).toHaveBeenCalledWith({ 
    name: name, 
    email: email, 
    password: password, 
    password_confirmation: password 
    }); 
} 

@ Marc è corretto affermare che il problema è con l'utilizzo di bind e il modo Javascript invia gli eventi "a volte/di solito/sempre "nel prossimo ciclo di eventi (la sua natura asincrona funziona), quindi visto che stai spiando un callback, vuoi assicurarti che i tuoi test siano scritti per tenere conto di quel comportamento asincrono.

Mentre i test sono scritti, si corre il rischio che il primo test non venga superato sporadicamente (sono sorpreso che funzioni così com'è). Stai testando una callback di eventi asincroni in modo non asincrono ... ha senso?

Problemi correlati