2011-11-26 22 views
22

Esta es mi acción:¿Cómo realizar una prueba unitaria de un controlador JSON?

def my_action 
    str = ... # get json str somehow 
    render :json => str 
end 

Esta es mi prueba:

test "my test" do 
    post(:my_action, {'param' => "value"}  
    assert_response :success 
end 

quiero añadir otra afirmación de que el JSON emitida contiene algún valor. ¿Cómo puedo hacerlo en una prueba unitaria de controlador, no mediante el análisis del resultado de la vista?

+1

¿No sería más fácil analizar la respuesta json? – jdeseno

+0

Tenía la impresión de que las pruebas unitarias realmente no invocan la vista. Es el caso? En caso afirmativo, ¿qué tipo de prueba es lo que busco (ver?) –

+1

Creo que esta pregunta ya fue discutida [aquí] (http://stackoverflow.com/questions/336716/how-to-test-json-result-from -rails-functional-tests). Lo que estás haciendo no es unidad, sino prueba funcional. Y en realidad representa la vista. –

Respuesta

43

Al igual que las personas comentadas anteriormente, esta sería una prueba funcional.

La mejor manera probablemente sería realizar una solicitud, analizar el cuerpo de la respuesta JSON y hacer coincidirlo con el resultado esperado.

Si tengo companies_controller en Rspec usando factorygirl:

describe "GET 'show'" do 

    before(:each) do 
    @company = Factory(:company) 
    get 'show', :format => :json, :id => @company.id 
    end 

    it "should be successful" do 
    response.should be_success 
    end 

    it "should return the correct company when correct id is passed" do 
    body = JSON.parse(response.body) 
    body["id"].should == @company.id 
    end 

end 

Puede probar otros atributos de la misma manera. Además, normalmente tengo el contexto invalid donde trataría de pasar parámetros no válidos.

+0

¿FactoryGirl no necesita un modelo, por lo que en su ejemplo, debe tener un modelo para "empresa"? – Ninja

+0

Has salvado a mi hombre del día. muchas gracias. – Abhinay

15

El uso de pruebas funcionales incorporados en Rails:

require 'test_helper' 

class ZombiesControllerTest < ActionController::TestCase 

    setup do 
    @request.headers['Accept'] = Mime::JSON 
    @request.headers['Content-Type'] = Mime::JSON.to_s 

    end 

    test "should post my action" do 
    post :my_action, { 'param' => "value" }, :format => "json" 
    assert_response :success 
    body = JSON.parse(response.body) 
    assert_equal "Some returned value", body["str"] 
    end 

end 
+0

Esto funciona cuando tiene una función responder_ que devuelve datos diferentes basados ​​en los diferentes bloques. En el ejemplo anterior, el póster define el método en el que se envía la PETICIÓN al controlador, para activar el bloque responder_ a la derecha. – FlyingV

3

Mi aproximación a esto es ligeramente diferente si estoy usando la gema Jbuilder que ya está disponible en el equipo de rieles. (Este enfoque se aplica a otras gemas que rinden JSON o XML como vistas). Prefiero las pruebas unitarias sobre las pruebas funcionales siempre que sea posible, ya que pueden ser bastante más rápidas. Con Jbuilder puede transformar la mayoría de las pruebas en pruebas unitarias.

Sí, todavía tiene pruebas funcionales en el controlador, pero hay muy pocas y no analizan el JSON. La prueba funcional únicamente prueba la lógica del controlador, no el JSON renderizado. Una prueba funcional para una petición válida podría afirmar lo siguiente (RSpec):

assert_response :success 
    expect(response).to render_template(:show) 
    expect(assigns(:item).id).to eq(expected_item.id) 

Sólo estoy verificando que éste tiene éxito, se hace que la plantilla, y se pasa el elemento a la plantilla. En este punto, la vista tiene la información que necesita para realizar la representación adecuada.

Ahora pruebe el JSON representado por la unidad que prueba la vista de Jbuilder.

describe 'api/v1/items/show.json.jbuilder' do 
    it 'includes foo' do 
    assign(:item, account.build(foo: 'bar')) 

    render 

    json = JSON.parse(rendered) 
    expect(json['item']['foo']).to eq('bar') 
    end 

    # A bunch of other JSON tests... 
1

Esta prueba controlador funcionado bien para mí usando Minitest con rieles 4.2.4:

require 'test_helper' 

class ThingsControllerTest < ActionController::TestCase 

    test "should successfully create a new thing" do 
    assert_difference 'Thing.count' do 
     @request.headers["Accept"] = "application/json" 

     post(:create, {thing: {name: "My Thing"}}) 
    end 

    assert_response :success 

    json_response = JSON.parse(@response.body) 
    assert_equal json_response["name"], "My Thing" 
    end 

end 

Y esto funcionó en la forma de una prueba de integración.

require 'test_helper' 

class ThingsRequestsTest < ActionDispatch::IntegrationTest 

    test "creates new thing" do 
    assert_difference 'Thing.count' do 
     post("/things.json", {thing: { name: "My Thing"}}) 
    end 

    assert_equal 201, status 

    json_response = JSON.parse(@response.body) 
    assert_equal json_response["name"], "My Thing" 
    end 

end 

Honestamente, es raro tratando de mantener los matices sintácticos directamente desde un tipo de prueba a otra.

Cuestiones relacionadas